Vuejs и Vue.set (), обновить массив


93

Я новичок в Vuejs. Что-то сделал, но не знаю, как это просто / правильно.

что я хочу

Я хочу несколько дат в массиве и обновляю их по событию. Сначала попробовал Vue.set, но ничего не вышло. Теперь после изменения элемента моего массива:

this.items[index] = val;
this.items.push();

Я ничего не нажимаю () в массив, и он обновляется .. Но иногда последний элемент каким-то образом скрывается ... Я думаю, что это решение немного взломано, как я могу сделать его стабильным?

Вот простой код:

new Vue({
  el: '#app',
  data: {
  	f: 'DD-MM-YYYY',
    items: [
      "10-03-2017",
      "12-03-2017"
    ]
  },
  methods: {
    
    cha: function(index, item, what, count) {
    	console.log(item + " index > " + index);
      val = moment(this.items[index], this.f).add(count, what).format(this.f);
  		this.items[index] = val;
      this.items.push();
      console.log("arr length:  " + this.items.length);
    }
  }
})
ul {
  list-style-type: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.11/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
<div id="app">
  <ul>
    <li v-for="(index, item) in items">
    <br><br>
      <button v-on:click="cha(index, item, 'day', -1)">
      - day</button>
      {{ item }}
      <button v-on:click="cha(index, item, 'day', 1)">
      + day</button>
    <br><br>
    </li>
  </ul>
</div>

Ответы:


57

VueJS не может улавливать ваши изменения состояния, если вы манипулируете такими массивами.

Как объясняется в разделе Общие вопросы для начинающих , вам следует использовать методы массива, такие как push, splice или что-то еще, и никогда не изменять индексы, подобные этому, a[2] = 2или свойство .length массива.

new Vue({
  el: '#app',
  data: {
    f: 'DD-MM-YYYY',
    items: [
      "10-03-2017",
      "12-03-2017"
    ]
  },
  methods: {

    cha: function(index, item, what, count) {
      console.log(item + " index > " + index);
      val = moment(this.items[index], this.f).add(count, what).format(this.f);

      this.items.$set(index, val)
      console.log("arr length:  " + this.items.length);
    }
  }
})
ul {
  list-style-type: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.11/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
<div id="app">
  <ul>
    <li v-for="(index, item) in items">
      <br><br>
      <button v-on:click="cha(index, item, 'day', -1)">
      - day</button> {{ item }}
      <button v-on:click="cha(index, item, 'day', 1)">
      + day</button>
      <br><br>
    </li>
  </ul>
</div>


1
Как сказано в документации, $ set - это просто красивый .splice (). Это имеет смысл, потому что, как говорится в документации, вы должны изменять массив, используя его методы.
— Borjante

1
Пожалуйста, не комбинируйте отступы табуляции с пробелами, размер табуляции явно отличается в приложении SE, что затрудняет чтение вашего кода
— Ferrybig

В моем случае оператор распространения ES6 для операции push явно не работает с vue
— Mathias S

117

РЕДАКТИРОВАТЬ 2

  • Для всех изменений объекта, требующих реактивности, используйтеVue.set(object, prop, value)
  • Для мутаций массива вы можете посмотреть список поддерживаемых в настоящее время здесь

ИЗМЕНИТЬ 1

Для vuex вы захотите сделать Vue.set(state.object, key, value)


Оригинал

Так что только для тех, кто задается этим вопросом. Он появляется в какой-то момент в Vue 2. * они удалили this.items.$set(index, val)в пользу this.$set(this.items, index, val).

Сплайс все еще доступен, и вот ссылка на методы мутации массива, доступные в ссылке vue .


Какую строку мне нужно указать в качестве индекса?
— Kokodoko

@Kokodoko, можешь пояснить, что ты пытаешься сделать? Если это массив, это должно быть число для индекса. Строка будет, если вы устанавливаете поле для объекта.
— Мартин Калверт,

А, ладно, моя IDE настаивала, что это должна быть строка, должно быть глюк.
— Kokodoko

Vue.set не для vuex. И этот. $ Set устарел.
— atilkan

2
@MartinCalvert Он говорит «при добавлении свойства к объекту». Это основная цель Vue.set, не связанная только с vuex. Устарело, я прочитал это по ссылке, но теперь читаю снова, я не совсем понимаю. stackoverflow.com/questions/36671106/…
— atilkan

11

Как указывалось ранее - VueJS просто не может отслеживать эти операции (назначение элементов массива). Все операции, которые отслеживает VueJS с массивом, находятся здесь . Но скопирую еще раз:

  • От себя()
  • поп ()
  • сдвиг()
  • unshift ()
  • сращивание ()
  • Сортировать()
  • обеспечить регресс()

В процессе разработки возникает проблема - как с этим жить :).

push (), pop (), shift (), unshift (), sort () и reverse () довольно просты и помогают вам в некоторых случаях, но основное внимание уделяется splice () , который позволяет вам эффективно изменять массив это будет отслеживаться VueJs. Так что могу поделиться некоторыми подходами, которые наиболее часто используются при работе с массивами.

Вам нужно заменить элемент в массиве:

// note - findIndex might be replaced with some(), filter(), forEach() 
// or any other function/approach if you need 
// additional browser support, or you might use a polyfill
const index = this.values.findIndex(item => {
          return (replacementItem.id === item.id)
        })
this.values.splice(index, 1, replacementItem)

Примечание: если вам просто нужно изменить поле элемента - вы можете сделать это просто:

this.values[index].itemField = newItemFieldValue

И это будет отслеживаться VueJS, поскольку отслеживаются поля элемента (объекта).

Вам нужно очистить массив:

this.values.splice(0, this.values.length)

На самом деле вы можете сделать гораздо больше с помощью этой функции splice () - ссылка w3schools. Вы можете добавлять несколько записей, удалять несколько записей и т. Д.

Vue.set () и Vue.delete ()

Vue.set () и Vue.delete () могут использоваться для добавления поля в вашу версию пользовательского интерфейса данных. Например, вам нужны дополнительные рассчитанные данные или флаги в ваших объектах. Вы можете сделать это для своих объектов или списка объектов (в цикле):

 Vue.set(plan, 'editEnabled', true) //(or this.$set)

И отправьте отредактированные данные обратно в серверную часть в том же формате, сделав это до вызова Axios:

 Vue.delete(plan, 'editEnabled') //(or this.$delete)

0

Одна альтернатива - и более легкий подход к вашей проблеме - может быть, просто временно отредактировать массив, а затем назначить весь массив обратно вашей переменной. Поскольку Vue не отслеживает отдельные элементы, он будет следить за обновлением всей переменной.

Так что это тоже должно работать:

var tempArray[];

tempArray = this.items;

tempArray[targetPosition]  = value;

this.items = tempArray;

Тогда это также должно обновить вашу DOM.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.