Привязка класса Vuejs не работает при начальном рендеринге

У меня странная проблема с тем, что VueJS не устанавливает класс для элемента в цикле v-for при первой загрузке страницы. Он работает после того, как я нажимаю на него, чтобы включать и выключать выбранный атрибут, но когда выбрано изначально истинно, строка не выделяется. Таким образом, для «синхронизации» экрана с данными требуется 2 клика.

<tbody>
  <tr v-for="v in listOfItems" :key="v.id" :class="{ selected: v.selected }" v-on:click="function(){ itemSelected(v) }">
     <td style="text-align:right"><span v-text="v.selected"></span></td>
     <td style="text-align:right"><span v-text="v.label"></span></td>
   </tr>
</tbody>

function itemSelected(row) {
    row.selected = !row.selected
    app.$nextTick(function() {
        console.log( $('tr.selected').length )
    })
    return false
}

Массив изначально загружается перед отображением экрана с помощью:

app.listOfItems = [{
    id: 100,
    label: 'Item 100',
    selected: true
}]

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


person Brad G.    schedule 18.01.2018    source источник
comment
Почему бы не просто v-on:click="v.selected = !v.selected"?   -  person Bert    schedule 18.01.2018
comment
Можете ли вы уточнить, что означает до отображения экрана? Когда именно в жизненном цикле Vue вы загружаете listOfItems?   -  person PatrickSteele    schedule 18.01.2018


Ответы (1)


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

Создание такого фрагмента — хорошая идея во всех смыслах: это может помочь вам самостоятельно обнаружить проблему; он может установить, находится ли проблема в коде, в котором, по вашему мнению, она находится; это дает вам практику; это дает потенциальным ответчикам отправную точку. Я действительно хочу, чтобы больше людей делали это.

const app = new Vue({
  el: '#app',
  data: {
    listOfItems: [{
      id: 100,
      label: 'Item 100',
      selected: true
    }]
  },
  methods: {
    itemSelected(row) {
      row.selected = !row.selected
      app.$nextTick(function() {
        console.log($('tr.selected').length)
      })
      return false
    }
  }
});
.selected {
  background-color: lightgray;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<table id="app">
  <tbody>
    <tr v-for="v in listOfItems" :key="v.id" :class="{ selected: v.selected }" v-on:click="function(){ itemSelected(v) }">
      <td style="text-align:right"><span v-text="v.selected"></span></td>
      <td style="text-align:right"><span v-text="v.label"></span></td>
    </tr>
  </tbody>
</table>

person Roy J    schedule 18.01.2018
comment
Спасибо за ответы. Я постараюсь ответить на каждый комментарий: во-первых, причина для функции вместо встроенного переключения заключается в том, что функция выполняет другие действия, связанные с приложением — удалено здесь для простоты. Что касается использования фрагмента кода, я до сих пор не знал об этой функции SO, так что спасибо. Наконец, что касается того, как и когда загружается listOfItems, почему это имеет значение? Когда я проверяю это в консоли отладки, значения верны. Разве реактивность не должна делать свое дело всякий раз, когда загружаются данные? Ваш фрагмент работает, поэтому я очень смущен, почему не мой. - person Brad G.; 19.01.2018
comment
Реактивность сделает свое дело, если данные загружены таким образом, чтобы быть реактивными. Возможно, вы вставили данные нереактивным способом, хотя Я не знаю, что впоследствии сделает его реактивным, как вы описываете. - person Roy J; 19.01.2018
comment
Я нашел проблему. В функции перехода, которая запускается при переходе с одного экрана на другой в моем SPA, была строка для сброса всех выбранных классов, независимо от модели данных! Это был $('.selected').removeClass('selected'), который фреймворк запускал при загрузке страницы. Сложно найти. Так что реактивность Vue в конце концов сработала. Извините за кроличью нору, но я ценю всю помощь! - person Brad G.; 19.01.2018