Геттеры Vuex в вычисленных свойствах, показывающие undefined до полной загрузки страницы

Я пытаюсь создать вычисленные свойства, используя данные, извлеченные с помощью функции mapGetters в vuex, но я всегда получаю undefined, пока страница / dom не загрузится полностью.

Вот пример вычисляемого свойства isRegistered, которое я использую для скрытия / отображения определенных кнопок.

computed: {
      ...mapGetters(['solos', 'user']),
      isRegistered () {
        return this.solos.registered.indexOf(this.user._id) !== -1
      }
}

Вот HTML-код кнопок, использующих вычисляемое свойство isRegistered.

<a href="#" class="register-button" v-if="!isRegistered">REGISTER NOW</a>
<a href="#" class="registered-button" v-if="isRegistered">REGISTERED</a>

Я устанавливаю геттеры с помощью действия, которое я вызываю в созданной функции

created () {
      this.getTournament('solos').catch(err => {})
}

Вот мое действие по установке соответствующих геттеров

getTournament: ({commit}, type) => {
    return feathers.service('tournaments').find({
      query: {
        type: type,
        status: 'registering'
      }
    }).then(tourney => {
      commit(type.toUpperCase(), tourney.data[0])
    })
}

Вот соответствующая мутация

const mutations = {
  SOLOS (state, result) {
    state.solos = result;
  }
};

Вот соответствующий геттер

const getters = {
   solos (state) {
     return state.solos
   }
}

Проблема, с которой я столкнулся, заключается в том, что значение изначально отображается как undefined, пока PAGE / DOM не будет полностью загружен, в результате чего .indexOf выдает следующую ошибку:

TypeError: Cannot read property 'indexOf' of undefined

Единственный способ заставить это работать - использовать оператор if для вычисляемого свойства, который проверяет, загружены ли данные состояния.

isRegistered () {
  if (this.solos._id) return this.solos.registered.indexOf(this.user._id) !== -1
}

Это не похоже на то, что нужно делать. Что я делаю неправильно?


person Jayson H    schedule 25.05.2017    source источник
comment
Это правильный способ делать что-то. Javascript является защитным, вы должны проверить, находятся ли объекты на месте, прежде чем обращаться к внутренним свойствам объекта.   -  person Egor Stambakio    schedule 25.05.2017
comment
Ваш последний фрагмент кода в значительной степени соответствует тому, как вы должны это делать.   -  person Bert    schedule 25.05.2017
comment
Хорошо, спасибо вам обоим!   -  person Jayson H    schedule 25.05.2017


Ответы (1)


Вероятно, проблема в жизненном цикле vue.

В хуке created вычисленные свойства, наблюдатели и данные компонента инициализирован (выполняется синхронно), но метод получения соло выполняется внутри обещания (выполняется асинхронно), поэтому жизненный цикл продолжается без выполнения обещания.

Когда ловушка created завершена, наблюдатели были созданы, что означает, что если данные будут изменены, они будут отражены в DOM, но только после того, как обещание вернет результат, соло будут исполнены. Таким образом, при инициализации приложения обещание не заканчивается, но как только оно завершается, данные обновляются и отображаются.

Способ избежать этой ошибки - использовать v-if="solos.registered", но я все еще ищу лучший способ решить эту проблему.

person tomrlh    schedule 27.07.2017
comment
Вы нашли лучший способ сделать это? @tomurlh - person rat; 29.03.2018
comment
Нет, но v-if существует по уважительной причине, поэтому, учитывая, что он хорошо подходит для этого случая, его можно считать правильным решением. - person tomrlh; 15.12.2019