Vue 2-Accesorios mutantes vue-warn


Empecé https://laracasts.com/series/learning-vue-step-by-step series. Me detuve en la lección Vue, Laravel y AJAX con este error:

vue.js:2574 [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "list" (found in component <task>)

Tengo este código en main.js

Vue.component('task', {
    template: '#task-template',
    props: ['list'],
    created() {
        this.list = JSON.parse(this.list);
    }
});
new Vue({
    el: '.container'
})

Sé que el problema está en created() cuando sobreescribo la prop de lista, pero soy un novato en Vue, así que no sé cómo solucionarlo. ¿Alguien tiene una idea de cómo (y por favor explique por qué) arreglarlo?

Author: vaxquis, 2016-10-05

15 answers

Esto tiene que ver con el hecho de que mutar un prop localmente se considera un anti-patrón en el Sdv 2 (ver aquí)

Lo que debe hacer ahora, en caso de que desee mutar un prop localmente , es declarar un campo en su data que usa el valor props como valor inicial y luego mutar la copia:

Vue.component('task', {
    template: '#task-template',
    props: ['list'],
    data: function () {
        return {
            mutableList: JSON.parse(this.list);
        }
    }
});

Por favor vea también este número aquí

Espero que esto ayude


Nota 1: Tenga en cuenta que, según este post , usted debe no trate de usar el mismo nombre para su prop y data, es decir:

data: function () { return { list: JSON.parse(this.list) } // WRONG!!

Nota 2: Dado que Siento que hay cierta confusión con respecto a props y reactividad , le sugiero que eche un vistazo a este hilo

 126
Author: ira,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-17 08:22:53

Vue solo le advierte: cambia la propiedad en el componente, pero cuando el componente padre vuelve a renderizar, "list" se sobrescribirá y perderá todos sus cambios. Así que es peligroso hacerlo.

Utilice la propiedad calculada insted así:

Vue.component('task', {
    template: '#task-template',
    props: ['list'],
    computed: {
        listJson: function(){
            return JSON.parse(this.list);
        }
    }
});
 25
Author: sealla,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-05 09:13:02

Apoyos hacia abajo, eventos hacia arriba. Ese Es El Patrón De Vue. El punto es que si intentas mutar un props pasa de padre. No funcionará y simplemente se sobrescribirá repetidamente por el componente padre. El componente hijo solo puede emitir evento para notificar al componente padre que haga sth. Si no te gustan estas restricciones, puedes usar VUEX (en realidad, este patrón succionará la estructura de componentes complejos, ¡deberías usar VUEX!)

 14
Author: edison xue,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-16 01:40:46

Si estás usando Lodash, puedes clonar el prop antes de devolverlo. Este patrón es útil si modifica esa prop tanto en el padre como en el hijo.

Digamos que tenemos prop list on component grid.

En El Componente Padre

<grid :list.sync="list"></grid>

En el Componente Secundario

props: ['list'],
methods:{
    doSomethingOnClick(entry){
        let modifiedList = _.clone(this.list)
        modifiedList = _.uniq(modifiedList) // Removes duplicates
        this.$emit('update:list', modifiedList)
    }
}
 12
Author: For the Name,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-21 20:56:29

No debe cambiar el valor de props en el componente hijo. Si realmente necesita cambiarlo, puede usar .sync. Al igual que esto

<your-component :list.sync="list"></your-component>

Vue.component('task', {
    template: '#task-template',
    props: ['list'],
    created() {
        this.$emit('update:list', JSON.parse(this.list))
    }
});
new Vue({
    el: '.container'
})
 8
Author: Potato Running,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-02 06:37:25

De acuerdo con VueJS 2.0, no debe mutar un prop dentro del componente. Solo son mutados por sus padres. Por lo tanto, debe definir variables en datos con diferentes nombres y mantenerlas actualizadas observando los accesorios reales. En caso de que la prop de lista sea cambiada por un padre, puede analizarla y asignarla a MutableList. Aquí hay una solución completa.

Vue.component('task', {
    template: ´<ul>
                  <li v-for="item in mutableList">
                      {{item.name}}
                  </li>
              </ul>´,
    props: ['list'],
    data: function () {
        return {
            mutableList = JSON.parse(this.list);
        }
    },
    watch:{
        list: function(){
            this.mutableList = JSON.parse(this.list);
        }
    }
});

Utiliza MutableList para representar su plantilla, por lo que mantiene su prop lista segura en el componente.

 4
Author: burak buruk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-06 08:15:58

También me enfrenté a este problema. La advertencia desapareció después de usar $on y $emit. Es algo así como usar $on y $emit recomendado para enviar datos del componente hijo al componente padre.

 3
Author: ihsanberahim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-15 13:55:26

El patrón de Sdv es simple: props abajo y events arriba. Suena simple, pero es fácil de olvidar al escribir un componente personalizado.

A partir de Vue 2.2.0 puede usar v-model (con propiedades calculadas). Encuentro que esta combinación crea una interfaz simple, limpia y consistente entre los componentes:

  • Cualquier props pasado a su componente permanece reactivo (es decir, no está clonado ni requiere una función watch para actualizar una copia local cuando cambia se detectan).
  • Los cambios se emiten automáticamente al padre.
  • Se puede utilizar con múltiples niveles de componentes.

Una propiedad calculada permite que el setter y el getter se definan por separado. Esto permite que el componente Task se reescriba de la siguiente manera:

Vue.component('Task', {
    template: '#task-template',
    props: ['list'],
    model: {
        prop: 'list',
        event: 'listchange'
    },
    computed: {
        listLocal: {
            get: function() {
                return this.list
            },
            set: function(value) {
                this.$emit('listchange', value)
            }
        }
    }
})  

La propiedad model define qué prop está asociado con v-model, y qué evento se emitirá en los cambios. A continuación, puede llamar a este componente desde el padre como sigue:

<Task v-model="parentList"></Task>

La propiedad calculada listLocal proporciona una interfaz simple getter y setter dentro del componente (piense en ello como si fuera una variable privada). Dentro de #task-template puede renderizar listLocal y seguirá siendo reactivo (es decir, si parentList cambia, actualizará el componente Task). También puede mutar listLocal llamando al setter (por ejemplo, this.listLocal = newList) y emitirá el cambio al padre.

Lo que es realmente genial acerca de este patrón es que se puede pasar listLocal a un niño componente de Task (usando v-model), y los cambios del componente hijo se propagarán al componente de nivel superior.

Por ejemplo, digamos que tenemos un componente EditTask separado para hacer algún tipo de modificación a los datos de la tarea. Usando el mismo patrón de propiedades v-model y calculadas podemos pasar listLocal al componente (usando v-model):

<script type="text/x-template" id="task-template">
    <div>
        <EditTask v-model="listLocal"></EditTask>
    </div>
</script>

Si EditTask emite un cambio, llamará apropiadamente a set() en listLocal y propagará el evento al nivel superior. Del mismo modo, el EditTask component también podría llamar a otros componentes secundarios (como elementos de formulario) usando v-model.

 3
Author: chris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-07 08:45:20

Si desea mutar props - use object.

<component :model="global.price"></component>

Componente:

props: ['model'],
methods: {
  changeValue: function() {
    this.model.value = "new value";
  }
}
 2
Author: Aiwass 418,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-12 13:31:10

Necesitas agregar un método calculado como este

Componente.vue

props: ['list'],
computed: {
    listJson: function(){
        return JSON.parse(this.list);
    }
}
 2
Author: ubastosir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-21 10:39:11

Flujo de Datos unidireccional, según https://vuejs.org/v2/guide/components.html , el componente sigue unidireccional Flujo de Datos, Todos los accesorios forman un enlace de un solo sentido entre la propiedad secundaria y la propiedad principal, cuando la propiedad principal se actualiza, fluirá hacia el hijo, pero no al revés, esto evita que los componentes secundarios muten accidentalmente los padres, lo que puede hacer que el flujo de datos de su aplicación sea más difícil de entender.

Además, cada vez que el padre componente es actualiza todos los accesorios en los componentes secundarios se actualizarán con el valor más reciente. Esto significa que no debe intentar mutar una propiedad dentro de un componente hijo. Si lo haces .vue te avisará en el consola.

Generalmente hay dos casos en los que es tentador mutar un objeto: La prop se usa para pasar un valor inicial; el componente hijo quiere usarlo como una propiedad de datos local después. El prop se pasa como un valor bruto que necesita ser transformado. Adecuado respuesta a estos casos de uso son: Defina una propiedad de datos local que utilice el valor inicial de la propiedad como su valor inicial:

props: ['initialCounter'],
data: function () {
  return { counter: this.initialCounter }
}

Defina una propiedad calculada que se calcula a partir del valor de la propiedad:

props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}
 2
Author: mryang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-04 03:09:55

No cambie las props directamente en los componentes.si necesita cambiarlo establezca una nueva propiedad como esta:

data () {
    return () {
        listClone: this.list
    }
}

Y cambiar el valor de listClone.

 2
Author: Tango5614,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-01 17:27:38

SDV.los accesorios js no deben ser mutados ya que esto se considera un Anti-Patrón en SDV.

El enfoque que tendrá que tomar es crear una propiedad de datos en su componente que haga referencia a la propiedad original prop de list

props: ['list'],
data: () {
  return {
    parsedList: JSON.parse(this.list)
  }
}

Ahora la estructura de la lista que se pasa al componente se hace referencia y se modifica a través de la propiedad data de su componente: -)

Si desea hacer algo más que analizar su propiedad list, utilice el Vue component ' computed propiedad. Esto le permite hacer mutaciones más profundas en sus accesorios.

props: ['list'],
computed: {
  filteredJSONList: () => {
    let parsedList = JSON.parse(this.list)
    let filteredList = parsedList.filter(listItem => listItem.active)
    console.log(filteredList)
    return filteredList
  }
}

El ejemplo anterior analiza su prop list y lo filtra hasta solo active list-tems, lo cierra para schnitts y giggles y lo devuelve.

nota : ambos data & computed en la plantilla se hace referencia a las propiedades de la misma manera, por ejemplo,

<pre>{{parsedList}}</pre>

<pre>{{filteredJSONList}}</pre>

Puede ser fácil pensar que una propiedad computed (siendo un método) necesita ser llamada... se no

 1
Author: Francis Leigh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-29 10:54:53

SDV.js considera esto un anti-patrón. Por ejemplo, declarar y establecer algunos accesorios como

this.propsVal = 'new Props Value'

Así que para resolver este problema tienes que tomar un valor de los props a los datos o la propiedad calculada de una instancia de Vue, como esto:

props: ['propsVal'],
data: function() {
   return {
       propVal: this.propsVal
   };
},
methods: {
...
}

Esto definitivamente funcionará.

 0
Author: iamsangeeth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-18 04:26:52

En este código, estoy usando un filtro para cada lista dentro de un componente. declaro una vaviable buscar de forma local al componente y creo un método computado para usar la lista y filtrarla..

Vue.component('comun-list',{
            props: ['list'],
            data: function () {
              return {
                buscar: '',
              }
            },
            template: `<ul class="list-group">
                            <li class="list-group-item">
                                <input type="text" v-model="buscar" class="form-control" />
                            </li>
                            <li v-for="item in buscarList" class="list-group-item">
                                {{item.title}}
                            </li>
                        </ul>`,
            computed: {
                buscarList: function(){
                    return this.list.filter((item) => item.title.includes(this.buscar));
                },
            },
        });
 -3
Author: Victor Ariel Pérez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-18 19:59:11