Vuejs y Vue.set (), matriz de actualización

92

Soy nuevo en Vuejs. Hice algo, pero no sé si es de la manera correcta o simple.

lo que quiero

Quiero algunas fechas en una matriz y actualizarlas en un evento. Primero probé Vue.set, pero no funcionó. Ahora, después de cambiar mi elemento de matriz:

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

Presiono () nada en la matriz y se actualizará ... Pero a veces el último elemento se ocultará, de alguna manera ... Creo que esta solución es un poco hacky, ¿cómo puedo hacerla estable?

El código simple está aquí:

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>

Johan Hoeksma
fuente

Respuestas:

57

VueJS no puede recoger sus cambios en el estado si manipula matrices como esta.

Como se explica en Common Beginner Gotchas , debe usar métodos de matriz como empujar, empalmar o lo que sea y nunca modificar los índices como este a[2] = 2ni la propiedad .length de una matriz.

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>

Borjante
fuente
1
Como se dice en los documentos, $ set es simplemente un bonito .splice (). Esto tiene sentido porque, como dicen en los documentos, debe modificar la matriz usando sus métodos.
Borjante
1
Por favor, no combine las sangrías de tabulación con sangrías de espacio, el tamaño de una pestaña es aparentemente diferente en la aplicación SE, lo que dificulta la lectura de su código
Ferrybig
En mi caso, el operador de propagación ES6 para la operación push no funciona correctamente con vue
Mathias S
116

EDITAR 2

  • Para todos los cambios de objetos que necesitan reactividad, utiliceVue.set(object, prop, value)
  • Para las mutaciones de matriz, puede consultar la lista admitida actualmente aquí

EDITAR 1

Para vuex querrás hacer Vue.set(state.object, key, value)


Original

Así que solo para otros que vienen a esta pregunta. Aparece en algún momento en Vue 2. * eliminaron this.items.$set(index, val)a favor de this.$set(this.items, index, val).

Splice todavía está disponible y aquí hay un enlace a los métodos de mutación de matriz disponibles en vue link .

Martín Calvert
fuente
¿Qué cadena debo proporcionar como "índice"?
Kokodoko
@Kokodoko, ¿puedes aclarar lo que estás tratando de hacer? Si es una matriz, debería ser un número para el índice. Una cadena sería si está configurando un campo en un objeto.
Martin Calvert
Ah, está bien, mi IDE insistió en que tenía que ser una cadena, debe ser un problema técnico.
Kokodoko
Vue.set no es para vuex. Y este. $ Set en desuso.
localhoost
2
@MartinCalvert Dice "al agregar propiedad al objeto". Ese es el propósito principal de Vue.set, no solo relacionado con vuex. Desactivación, lo leí en el enlace, pero ahora que leo de nuevo, no lo entiendo completamente. stackoverflow.com/questions/36671106/…
localhoost
10

Como se indicó anteriormente, VueJS simplemente no puede rastrear esas operaciones (asignación de elementos de matriz). Todas las operaciones rastreadas por VueJS con array están aquí . Pero los copiaré una vez más:

  • empujar()
  • popular()
  • cambio()
  • unshift ()
  • empalme()
  • ordenar()
  • contrarrestar()

Durante el desarrollo, te enfrentas a un problema: cómo vivir con eso :).

push (), pop (), shift (), unshift (), sort () y reverse () son bastante simples y lo ayudan en algunos casos, pero el enfoque principal se encuentra dentro del splice () , que le permite modificar efectivamente la matriz que sería rastreado por VueJs. Así que puedo compartir algunos de los enfoques que más se utilizan para trabajar con matrices.

Necesita reemplazar el elemento en la matriz:

// 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)

Nota: si solo necesita modificar un campo de elemento, puede hacerlo simplemente de la siguiente manera:

this.values[index].itemField = newItemFieldValue

Y esto sería rastreado por VueJS ya que los campos del elemento (Objeto) serían rastreados.

Necesitas vaciar la matriz:

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

En realidad, puede hacer mucho más con esta función splice () - enlace w3schools Puede agregar varios registros, eliminar varios registros, etc.

Vue.set () y Vue.delete ()

Vue.set () y Vue.delete () pueden usarse para agregar un campo a la versión de datos de la interfaz de usuario. Por ejemplo, necesita algunos datos o indicadores calculados adicionales dentro de sus objetos. Puede hacer esto para sus objetos o lista de objetos (en el ciclo):

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

Y envíe los datos editados de vuelta al back-end en el mismo formato haciendo esto antes de la llamada de Axios:

 Vue.delete(plan, 'editEnabled') //(or this.$delete)
Mykola Korol
fuente
0

Una alternativa, y un enfoque más ligero para su problema, podría ser simplemente editar la matriz temporalmente y luego asignar la matriz completa a su variable. Porque como Vue no observa elementos individuales, verá la actualización de toda la variable.

Entonces esto debería funcionar también:

var tempArray[];

tempArray = this.items;

tempArray[targetPosition]  = value;

this.items = tempArray;

Esto también debería actualizar su DOM.

Geole
fuente