Empecé https://laracasts.com/series/learning-vue-step-by-step series. Paré en la lección Vue, Laravel y AJAX con este error:
vue.js: 2574 [Vue warn]: evite mutar un accesorio directamente ya que el valor se sobrescribirá cada vez que el componente principal se vuelva a representar. En su lugar, use una propiedad de datos o calculada basada en el valor del accesorio. Prop siendo mutado: "lista" (encontrado en componente)
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 sobrescribo la lista de accesorios, pero soy un novato en Vue, así que no sé cómo solucionarlo. ¿Alguien tiene una idea de cómo (y explique por qué) solucionarlo?
javascript
vue.js
vuejs2
Dariusz Chowański
fuente
fuente
Respuestas:
Esto tiene que ver con el hecho de que mutar un accesorio localmente se considera un antipatrón en Vue 2
Lo que debe hacer ahora, en caso de que quiera mutar un accesorio localmente , es declarar un campo en su
data
que use elprops
valor como su valor inicial y luego mutar la copia:Puedes leer más sobre esto en la guía oficial de Vue.js
Nota 1: Nota Por favor, que usted debe no utilizar el mismo nombre para su
prop
edata
, es decir:Nota 2: Desde Siento que hay cierta confusión respecto
props
y reactividad , lo que sugeriría echar un vistazo a este hilofuente
El patrón Vue es
props
hacia abajo y haciaevents
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 ). He descubierto que esta combinación crea una interfaz simple, limpia y consistente entre componentes:
props
pasa a su componente permanece reactivo (es decir, no está clonado ni requiere unawatch
función para actualizar una copia local cuando se detectan cambios).Una propiedad calculada permite que el definidor y el captador se definan por separado. Esto permite que el
Task
componente se reescriba de la siguiente manera:La propiedad del modelo define qué
prop
está asociadov-model
y qué evento se emitirá en los cambios. Luego puede llamar a este componente desde el padre de la siguiente manera:La
listLocal
propiedad calculada proporciona una interfaz getter y setter simple dentro del componente (piense que es una variable privada). Dentro de#task-template
usted puede renderizarlistLocal
y permanecerá reactivo (es decir, siparentList
cambia, actualizará elTask
componente). También puede mutarlistLocal
llamando al configurador (por ejemplo,this.listLocal = newList
) y emitirá el cambio al padre.Lo bueno de este patrón es que puede pasar
listLocal
a un componente secundario deTask
(usarv-model
), y los cambios del componente secundario se propagarán al componente de nivel superior.Por ejemplo, supongamos que tenemos un
EditTask
componente separado para realizar algún tipo de modificación en los datos de la tarea. Al usar el mismov-model
patrón de propiedades calculadas podemos pasarlistLocal
al componente (usandov-model
):Si
EditTask
emite un cambio llamará apropiadamenteset()
enlistLocal
y por lo tanto propagar el evento para el nivel superior. Del mismo modo, elEditTask
componente también podría llamar a otros componentes secundarios (como elementos de formulario) usandov-model
.fuente
Vue simplemente te advierte: cambias la utilería en el componente, pero cuando el componente padre se vuelve a representar, se sobrescribirá la "lista" y perderás todos los cambios. Entonces es peligroso hacerlo.
Utilice la propiedad calculada en su lugar de esta manera:
fuente
Si está usando Lodash, puede clonar el accesorio antes de devolverlo. Este patrón es útil si modifica ese accesorio tanto en el padre como en el hijo.
Digamos que tenemos una lista de accesorios en la cuadrícula de componentes .
En componente principal
En componente infantil
fuente
Apoyos, eventos arriba. Ese es el patrón de Vue. El punto es que si intentas mutar los accesorios que pasan de un padre. No funcionará y el componente principal lo sobrescribe repetidamente. El componente hijo solo puede emitir un evento para notificar al componente padre que haga algo. Si no le gustan estas restricciones, puede usar VUEX (en realidad, este patrón absorberá la estructura de componentes complejos, ¡debe usar VUEX!)
fuente
No debe cambiar el valor de los accesorios en el componente hijo. Si realmente necesita cambiarlo, puede usarlo
.sync
. Solo asi<your-component :list.sync="list"></your-component>
fuente
De acuerdo con VueJs 2.0, no debe mutar un accesorio dentro del componente. Solo son mutados por sus padres. Por lo tanto, debe definir variables en los datos con diferentes nombres y mantenerlas actualizadas viendo accesorios reales. En caso de que un padre cambie el accesorio de la lista, puede analizarlo y asignarlo a mutableList. Aquí hay una solución completa.
Utiliza mutableList para representar su plantilla, por lo tanto, mantiene su accesorio de lista seguro en el componente.
fuente
no cambie los accesorios directamente en los componentes. Si necesita cambiarlo, establezca una nueva propiedad como esta:
Y cambie el valor de listClone.
fuente
La respuesta es simple: debe romper la mutación de apoyo directo asignando el valor a algunas variables de componentes locales (podrían ser propiedades de datos, calculadas con captadores, establecedores o observadores).
Aquí hay una solución simple usando el observador.
Es lo que uso para crear cualquier componente de entrada de datos y funciona bien. Cualquier nuevo dato enviado (v-model (ed)) desde el padre será observado por el observador de valores y se asignará a la variable de entrada y una vez que se reciba la entrada, podemos capturar esa acción y emitir entrada al padre sugiriendo que los datos son ingresados del elemento de forma.
fuente
También enfrenté este problema. La advertencia desapareció después de usar
$on
y$emit
. Es algo así como el uso$on
y se$emit
recomienda enviar datos del componente secundario al componente primario.fuente
Si quieres mutar los accesorios, usa object.
componente:
fuente
Necesita agregar un método calculado como este
componente.vue
fuente
Flujo de datos unidireccional, de acuerdo con https://vuejs.org/v2/guide/components.html , el componente sigue el flujo de datos unidireccional , todos los accesorios forman un enlace unidireccional entre la propiedad secundaria y el padre uno, cuando la propiedad padre se actualiza, fluirá hacia el niño pero no al revés, esto evita que los componentes hijos muten accidentalmente el padre, lo que puede dificultar la comprensión de los datos de su aplicación.
Además, cada vez que se actualiza el componente principal, todos los accesorios en los componentes secundarios se actualizarán con el último valor. Esto significa que no debe intentar mutar un accesorio dentro de un componente secundario. Si lo haces .vue te avisará en la consola.
Por lo general, hay dos casos en los que es tentador mutar un accesorio: el accesorio se usa para pasar un valor inicial; el componente hijo quiere usarlo luego como una propiedad de datos local. El accesorio se pasa como un valor bruto que necesita ser transformado. La respuesta adecuada a estos casos de uso es: Defina una propiedad de datos local que use el valor inicial del accesorio como su valor inicial:
Defina una propiedad calculada que se calcule a partir del valor del accesorio:
fuente
Los accesorios de Vue.js no deben mutarse, ya que esto se considera un Anti-Pattern en Vue.
El enfoque que tendrá que tomar es la creación de una propiedad de datos en el componente que hace referencia el original prop propiedad de la lista
Ahora su estructura de lista que se pasa al componente se referencia y muta a través de la
data
propiedad de su componente :-)Si desea hacer algo más que analizar su propiedad de lista, utilice la
computed
propiedad del componente Vue . Esto le permite hacer mutaciones más profundas en sus accesorios.El ejemplo anterior analiza su accesorio de lista y lo filtra a solo elementos de lista activos , lo cierra para detectar schnitts y risitas y lo devuelve.
nota : ambas propiedades
data
ycomputed
están referenciadas en la plantilla de la misma manera, por ejemploPuede ser fácil pensar que una
computed
propiedad (siendo un método) necesita ser llamada ... nofuente
Quizás esto satisfaga sus necesidades.
fuente
Agregando a la mejor respuesta,
La configuración de accesorios por una matriz está destinada a desarrollo / creación de prototipos, en producción, asegúrese de establecer los tipos de accesorios ( https://vuejs.org/v2/guide/components-props.html ) y establecer un valor predeterminado en caso de que el accesorio no haya sido poblado por el padre, como tal.
De esta manera, al menos obtiene un objeto vacío en
mutableList
lugar de un error JSON.parse si no está definido.fuente
Vue.js considera esto un antipatrón. Por ejemplo, declarando y configurando algunos accesorios como
Entonces, para resolver este problema, debe tomar un valor de los accesorios a los datos o la propiedad calculada de una instancia de Vue, como esta:
Esto definitivamente funcionará.
fuente
Además de lo anterior, para otros que tengan el siguiente problema:
"Si el valor de los accesorios no es obligatorio y, por lo tanto, no siempre se devuelve, los datos pasados volverían
undefined
(en lugar de estar vacíos)". Lo que podría alterar<select>
el valor predeterminado, lo resolví comprobando si el valor está configuradobeforeMount()
(y configúrelo si no) de la siguiente manera:JS:
HTML:
fuente
Quiero dar esta respuesta que ayuda a evitar el uso de mucho código, observadores y propiedades calculadas. En algunos casos, esta puede ser una buena solución:
Los accesorios están diseñados para proporcionar comunicación unidireccional.
Cuando tienes un
show/hide
botón modal con un accesorio, la mejor solución para mí es emitir un evento:Luego agregue oyente al elemento modal:
(En este caso, la utilería
show
probablemente no sea necesaria porque puede usar una fácilv-if="show"
directamente en el modal base)fuente
Personalmente, siempre sugiero que si necesita mutar los accesorios, primero páselos a la propiedad calculada y regrese a partir de ahí, luego puede mutar los accesorios fácilmente, incluso si puede rastrear la mutación del accesorio, si están siendo mutados de otro componente también o podemos ver también.
fuente
Debido a que Vue props es un flujo de datos unidireccional, esto evita que los componentes secundarios muten accidentalmente el estado del padre.
Del documento oficial de Vue, encontraremos 2 formas de resolver este problema
Si el componente hijo quiere usar accesorios como datos locales, es mejor definir una propiedad de datos local.
El accesorio se pasa como un valor bruto que necesita ser transformado. En este caso, es mejor definir una propiedad calculada utilizando el valor del accesorio:
fuente
¡SÍ !, los atributos de mutación en vue2 son antipatrón. PERO ... ¡Solo rompa las reglas usando otras reglas y avance! Lo que necesita es agregar el modificador .sync a su atributo de componente en el ámbito de paret.
<your-awesome-components :custom-attribute-as-prob.sync="value" />
🤡 Es simple, matamos al batman 😁
fuente
Para cuando TypeScript es su idioma preferido. de desarrollo
y no
fuente
A continuación hay un componente de snack bar, cuando doy el snackbar variable directamente en v-model como este si funciona pero en la consola, dará un error como
Evite mutar un accesorio directamente ya que el valor se sobrescribirá cada vez que el componente principal se vuelva a representar. En su lugar, use una propiedad de datos o calculada basada en el valor del accesorio.
La forma correcta de deshacerse de este error de mutación es usar vigilante
Entonces, en el componente principal donde cargará este snack bar, simplemente puede hacer este código
Esto funcionó para mi
fuente