J'ai commencé la série https://laracasts.com/series/learning-vue-step-by-step . Je me suis arrêté sur la leçon Vue, Laravel et AJAX avec cette erreur:
vue.js: 2574 [Vue warn]: évitez de muter directement un accessoire car la valeur sera écrasée à chaque fois que le composant parent sera à nouveau rendu. Au lieu de cela, utilisez une donnée ou une propriété calculée en fonction de la valeur de l'accessoire. Prop en cours de mutation: "liste" (trouvée dans le composant)
J'ai ce code dans main.js
Vue.component('task', {
template: '#task-template',
props: ['list'],
created() {
this.list = JSON.parse(this.list);
}
});
new Vue({
el: '.container'
})
Je sais que le problème est dans created () lorsque j'écrase le prop de liste, mais je suis un débutant dans Vue, donc je ne sais absolument pas comment le résoudre. Quelqu'un a-t-il une idée de la façon (et expliquez pourquoi) de le résoudre?
javascript
vue.js
vuejs2
Dariusz Chowański
la source
la source
Réponses:
Cela a à voir avec le fait que la mutation locale d'un accessoire est considérée comme un anti-motif dans Vue 2
Ce que vous devez faire maintenant, au cas où vous voudriez muter un accessoire localement , est de déclarer un champ dans votre
data
qui utilise laprops
valeur comme valeur initiale, puis de muter la copie:Vous pouvez en savoir plus à ce sujet sur le guide officiel de Vue.js
Remarque 1: Veuillez noter que vous ne devez pas utiliser le même nom pour votre
prop
etdata
, c'est-à-dire:Note 2: Puisqu'il me semble qu'il y a une certaine confusion concernant
props
et la réactivité , je vous suggère de jeter un œil sur ce filla source
Le modèle Vue est
props
vers le bas et vers leevents
haut. Cela semble simple, mais il est facile de l'oublier lors de l'écriture d'un composant personnalisé.Depuis Vue 2.2.0, vous pouvez utiliser v-model (avec des propriétés calculées ). J'ai trouvé que cette combinaison crée une interface simple, propre et cohérente entre les composants:
props
passé à votre composant reste réactif (c'est-à-dire qu'il n'est pas cloné et ne nécessite pas dewatch
fonction pour mettre à jour une copie locale lorsque des changements sont détectés).Une propriété calculée permet au setter et au getter d'être définis séparément. Cela permet au
Task
composant d'être réécrit comme suit:La propriété model définit ce qui
prop
est associév-model
et quel événement sera émis lors des modifications. Vous pouvez ensuite appeler ce composant depuis le parent comme suit:La
listLocal
propriété calculée fournit une interface de lecture et de définition simple dans le composant (pensez-y comme étant une variable privée). À l'intérieur,#task-template
vous pouvez effectuer le rendulistLocal
et il restera réactif (c'est-à-dire que si desparentList
modifications sont apportées, leTask
composant sera mis à jour ). Vous pouvez également muterlistLocal
en appelant le setter (par exemple,this.listLocal = newList
) et il émettra le changement au parent.Ce qui est génial avec ce modèle, c'est que vous pouvez passer
listLocal
à un composant enfant deTask
(usingv-model
), et les modifications du composant enfant se propageront au composant de niveau supérieur.Par exemple, disons que nous avons un
EditTask
composant séparé pour effectuer un type de modification sur les données de la tâche. En utilisant le mêmev-model
modèle de propriétés calculées, nous pouvons passerlistLocal
au composant (en utilisantv-model
):Si
EditTask
émet un changement , il appellera de façon appropriéeset()
surlistLocal
et ainsi propager l'événement au niveau supérieur. De même, leEditTask
composant peut également appeler d'autres composants enfants (tels que des éléments de formulaire) à l'aide dev-model
.la source
Vue vous avertit simplement: vous modifiez l'accessoire dans le composant, mais lorsque le composant parent se re-rend, "list" sera écrasé et vous perdrez toutes vos modifications. Il est donc dangereux de le faire.
Utilisez plutôt la propriété calculée comme ceci:
la source
Si vous utilisez Lodash, vous pouvez cloner l'accessoire avant de le retourner. Ce modèle est utile si vous modifiez cet accessoire sur le parent et l'enfant.
Disons que nous avons une liste d' accessoires sur la grille des composants .
Dans le composant parent
Dans le composant enfant
la source
Props down, events up. C'est le modèle de Vue. Le fait est que si vous essayez de faire muter les accessoires en passant d'un parent. Cela ne fonctionnera pas et il est simplement écrasé à plusieurs reprises par le composant parent. Le composant enfant peut uniquement émettre un événement pour avertir le composant parent de faire qc. Si vous n'aimez pas ces restrictions, vous pouvez utiliser VUEX (en fait, ce modèle aspirera dans une structure de composants complexes, vous devriez utiliser VUEX!)
la source
Vous ne devez pas modifier la valeur des accessoires dans le composant enfant. Si vous avez vraiment besoin de le changer, vous pouvez utiliser
.sync
. Juste comme ça<your-component :list.sync="list"></your-component>
la source
Selon VueJs 2.0, vous ne devez pas muter un accessoire à l'intérieur du composant. Ils ne sont mutés que par leurs parents. Par conséquent, vous devez définir des variables dans les données avec des noms différents et les maintenir à jour en regardant les accessoires réels. Si le prop de liste est modifié par un parent, vous pouvez l'analyser et l'affecter à mutableList. Voici une solution complète.
Il utilise mutableList pour rendre votre modèle, ainsi vous gardez votre prop de liste en sécurité dans le composant.
la source
ne modifiez pas les accessoires directement dans les composants.Si vous avez besoin de le modifier, définissez une nouvelle propriété comme celle-ci:
Et changez la valeur de listClone.
la source
La réponse est simple, vous devez briser la mutation prop directe en attribuant la valeur à certaines variables de composant local (il peut s'agir d'une propriété de données, calculée avec des getters, des setters ou des observateurs).
Voici une solution simple utilisant l'observateur.
C'est ce que j'utilise pour créer des composants d'entrée de données et cela fonctionne très bien. Toutes les nouvelles données envoyées (v-model (ed)) du parent seront surveillées par l'observateur de valeur et affectées à la variable d'entrée et une fois que l'entrée est reçue, nous pouvons attraper cette action et émettre une entrée au parent suggérant que les données sont entrées à partir de l'élément de formulaire.
la source
J'ai également fait face à ce problème. L'avertissement est parti après avoir utilisé
$on
et$emit
. C'est quelque chose comme l'utilisation$on
et$emit
recommandé d'envoyer des données du composant enfant au composant parent.la source
Si vous voulez faire muter les accessoires - utilisez object.
composant:
la source
Vous devez ajouter une méthode calculée comme celle-ci
component.vue
la source
Flux de données unidirectionnel, selon https://vuejs.org/v2/guide/components.html , le composant suit un flux de données unidirectionnel, tous les accessoires forment une liaison unidirectionnelle entre la propriété enfant et le parent Premièrement, lorsque la propriété parent est mise à jour, elle descendra vers l'enfant mais pas l'inverse, cela empêche les composants enfants de muter accidentellement ceux du parent, ce qui peut rendre le flux de données de votre application plus difficile à comprendre.
De plus, chaque fois que le composant parent est mis à jour, tous les accessoires des composants enfants seront actualisés avec la dernière valeur. Cela signifie que vous ne devez pas tenter de muter un accessoire dans un composant enfant. Si vous le faites, .vue vous en avertira dans la console.
Il y a généralement deux cas où il est tentant de muter un accessoire: Le prop est utilisé pour passer une valeur initiale; le composant enfant veut ensuite l'utiliser comme propriété de données locale. L'accessoire est transmis en tant que valeur brute qui doit être transformée. La bonne réponse à ces cas d'utilisation est: Définissez une propriété de données locales qui utilise la valeur initiale de l'accessoire comme valeur initiale:
Définissez une propriété calculée qui est calculée à partir de la valeur de l'accessoire:
la source
Les accessoires Vue.js ne doivent pas être mutés car cela est considéré comme un Anti-Pattern dans Vue.
L'approche que vous devrez adopter consiste à créer une propriété de données sur votre composant qui référence la propriété prop d' origine de list
Maintenant, la structure de votre liste qui est passée au composant est référencée et mutée via la
data
propriété de votre composant :-)Si vous souhaitez faire plus que juste parse votre propriété de liste , puis utiliser la composante Vue
computed
propriété. Cela vous permet de faire des mutations plus profondes sur vos accessoires.L'exemple ci-dessus analyse votre prop de liste et le filtre aux seuls éléments de liste actifs , le déconnecte pour les schnitts et les rires et le renvoie.
Note : les deux
data
etcomputed
propriétés sont référencées dans le modèle même par exempleIl peut être facile de penser qu'une
computed
propriété (étant une méthode) doit être appelée ... ce n'est pas le casla source
Peut-être que cela répondra à vos besoins.
la source
Ajout de la meilleure réponse,
La définition des props par un tableau est destinée au développement / prototypage, en production, assurez-vous de définir les types de prop ( https://vuejs.org/v2/guide/components-props.html ) et définissez une valeur par défaut au cas où la prop ne l'aurait pas été rempli par le parent, comme tel.
De cette façon, vous obtenez au moins un objet vide au
mutableList
lieu d'une erreur JSON.parse s'il n'est pas défini.la source
Vous trouverez ci-dessous un composant de snack-bar, lorsque je donne la variable snackbar directement dans le v-model comme celui-ci si cela fonctionnera mais dans la console, cela donnera une erreur comme
Évitez de muter directement un accessoire car la valeur sera écrasée chaque fois que le composant parent sera à nouveau rendu. Au lieu de cela, utilisez une donnée ou une propriété calculée en fonction de la valeur de l'accessoire.
La bonne façon de se débarrasser de cette erreur de mutation est d'utiliser watcher
Donc, dans le composant principal où vous allez charger ce snack, vous pouvez simplement faire ce code
Cela a fonctionné pour moi
la source
Vue.js considère cela comme un anti-pattern. Par exemple, déclarer et définir des accessoires comme
Donc, pour résoudre ce problème, vous devez prendre une valeur des accessoires aux données ou à la propriété calculée d'une instance de Vue, comme ceci:
Cela fonctionnera certainement.
la source
En plus de ce qui précède, pour les autres ayant le problème suivant:
"Si la valeur des accessoires n'est pas requise et n'est donc pas toujours renvoyée, les données passées retourneront
undefined
(au lieu d'être vides)". Ce qui pourrait perturber la<select>
valeur par défaut, je l'ai résolu en vérifiant si la valeur est définiebeforeMount()
(et en la définissant sinon) comme suit:JS:
Html:
la source
Je veux donner cette réponse qui évite d'utiliser beaucoup de code, d'observateurs et de propriétés calculées. Dans certains cas, cela peut être une bonne solution:
Les accessoires sont conçus pour fournir une communication unidirectionnelle.
Lorsque vous avez un
show/hide
bouton modal avec un accessoire, la meilleure solution pour moi est d'émettre un événement:Ensuite, ajoutez un écouteur à l'élément modal:
(Dans ce cas, l'accessoire
show
est probablement inutile car vous pouvez utiliser un easyv-if="show"
directement sur la base-modal)la source
Personnellement, je suggère toujours que si vous avez besoin de muter les accessoires, passez-les d'abord à la propriété calculée et revenez de là, par la suite, on peut muter facilement les accessoires, même si vous pouvez suivre la mutation de l'accessoire, si ceux-ci sont mutés d'un autre composant aussi ou nous pouvons vous regarder aussi.
la source
Étant donné que les accessoires Vue sont un flux de données à sens unique, cela empêche les composants enfants de muter accidentellement l'état du parent.
À partir du document officiel Vue, nous trouverons 2 façons de résoudre ces problèmes
si le composant enfant souhaite utiliser des accessoires comme données locales, il est préférable de définir une propriété de données locales.
L'accessoire est transmis en tant que valeur brute qui doit être transformée. Dans ce cas, il est préférable de définir une propriété calculée en utilisant la valeur du prop:
la source
OUI !, la mutation des attributs dans vue2 est anti-pattern. MAIS ... enfreignez simplement les règles en utilisant d'autres règles, et allez de l'avant! Ce dont vous avez besoin est d'ajouter le modificateur .sync à votre attribut de composant dans la portée de paret.
<your-awesome-components :custom-attribute-as-prob.sync="value" />
🤡 C'est simple, nous tuons le batman 😁
la source
Pour lorsque TypeScript est votre langue préférée. de développement
et pas
la source