Dans les VueJs 2.0 docs , je ne trouve aucun crochet qui puisse écouter lorsque props
change.
Est-ce que VueJs a de tels crochets comme onPropsUpdated()
ou similaire?
Mettre à jour
Comme @wostex l'a suggéré, j'ai essayé de watch
ma propriété mais rien n'a changé. Puis j'ai réalisé que j'avais un cas particulier:
<template>
<child :my-prop="myProp"></child>
</template>
<script>
export default {
props: ['myProp']
}
</script>
Je passe myProp
que le composant parent reçoit au composant child
. Alors le watch: {myProp: ...}
ne fonctionne pas.
Vous pouvez watch
props pour exécuter du code lors de leurs modifications:
new Vue({
el: '#app',
data: {
text: 'Hello'
},
components: {
'child' : {
template: `<p>{{ myprop }}</p>`,
props: ['myprop'],
watch: {
myprop: function(newVal, oldVal) { // watch it
console.log('Prop changed: ', newVal, ' | was: ', oldVal)
}
}
}
}
});
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<child :myprop="text"></child>
<button @click="text = 'Another text'">Change text</button>
</div>
Avez-vous essayé cela?
watch: {
myProp: {
// the callback will be called immediately after the start of the observation
immediate: true,
handler (val, oldVal) {
// do your stuff
}
}
}
Il,
dans mon cas, j'avais besoin d'une solution où, à tout moment, les accessoires changeraient, je devais analyser à nouveau mes données. J'étais fatigué de faire de l'observateur séparé pour tous mes accessoires, alors j'ai utilisé ceci:
watch: {
$props: {
handler() {
this.parseData();
},
deep: true,
immediate: true,
},
Le point clé à retenir de cet exemple est d'utiliser deep: true
afin qu'il ne surveille pas seulement $ props, mais également ses valeurs imbriquées telles que p. Ex. props.myProp
Vous pouvez en savoir plus sur ces options de surveillance étendues ici: https://vuejs.org/v2/api/#vm-watch
Vous devez comprendre la hiérarchie des composants que vous rencontrez et la manière dont vous transmettez les accessoires. Il est certain que votre cas est spécial et que les développeurs ne le rencontrent généralement pas.
Composant parent -myProp-> Composant enfant -myProp-> Composant petits-enfants
Si myProp est modifié dans le composant parent, il sera reflété dans le composant enfant également.
Et si myProp est modifié dans le composant enfant, il sera reflété dans le composant petitchild également.
Donc, si myProp est modifié dans le composant parent, alors il sera reflété dans le composant petitchild. (jusqu'ici tout va bien).
Par conséquent, dans la hiérarchie, vous n'avez rien à faire, les accessoires seront intrinsèquement réactifs.
Parlons maintenant de la hiérarchie
Si myProp est modifié dans le composant grandChild, il ne sera pas reflété dans le composant enfant. Vous devez utiliser le modificateur .sync dans enfant et émettre un événement à partir du composant grandChild.
Si myProp est modifié dans le composant enfant, il ne sera pas reflété dans le composant parent. Vous devez utiliser le modificateur .sync dans parent et émettre un événement à partir du composant enfant.
Si myProp est modifié dans le composant grandChild, il ne sera pas reflété dans le composant parent (évidemment). Vous devez utiliser le modificateur .sync enfant et émettre un événement du composant grandchild, puis regarder le composant prop dans le composant enfant et émettre un événement lors de la modification qui est écoutée par le composant parent à l'aide du modificateur .sync.
Voyons du code pour éviter toute confusion
Parent.vue
<template>
<div>
<child :myProp.sync="myProp"></child>
<input v-model="myProp"/>
<p>{{myProp}}</p>
</div>
</template>
<script>
import child from './Child.vue'
export default{
data(){
return{
myProp:"hello"
}
},
components:{
child
}
}
</script>
<style scoped>
</style>
Child.vue
<template>
<div> <grand-child :myProp.sync="myProp"></grand-child>
<p>{{myProp}}</p>
</div>
</template>
<script>
import grandChild from './Grandchild.vue'
export default{
components:{
grandChild
},
props:['myProp'],
watch:{
'myProp'(){
this.$emit('update:myProp',this.myProp)
}
}
}
</script>
<style>
</style>
Petit-enfant.vue
<template>
<div><p>{{myProp}}</p>
<input v-model="myProp" @input="changed"/>
</div>
</template>
<script>
export default{
props:['myProp'],
methods:{
changed(event){
this.$emit('update:myProp',this.myProp)
}
}
}
</script>
<style>
</style>
Mais après cela, vous ne ferez pas attention aux avertissements criants de vue disant
'Évitez de muter directement un accessoire, car la valeur sera écrasée à chaque nouvelle restitution du composant parent.'
Encore une fois, comme je l’ai mentionné précédemment, la plupart des développeurs ne rencontrent pas ce problème, car c’est un modèle anti-modèle. C'est pourquoi vous obtenez cet avertissement.
Mais afin de résoudre votre problème (selon votre conception). Je crois que vous devez faire le travail ci-dessus autour (bidouille pour être honnête). Je vous recommande néanmoins de repenser votre conception et de réduire les risques de bugs.
J'espère que ça aide.
Je ne sais pas si vous l'avez résolu (et si je comprends bien), mais voici mon idée:
Si le parent reçoit myProp et que vous souhaitez le transmettre à l'enfant et le regarder dans l'enfant, il doit alors disposer d'une copie de myProp (non de référence).
Essaye ça:
new Vue({
el: '#app',
data: {
text: 'Hello'
},
components: {
'parent': {
props: ['myProp'],
computed: {
myInnerProp() { return myProp.clone(); } //eg. myProp.slice() for array
}
},
'child': {
props: ['myProp'],
watch: {
myProp(val, oldval) { now val will differ from oldval }
}
}
}
}
et en html:
<child :my-prop="myInnerProp"></child>
en fait, vous devez être très prudent lorsque vous travaillez sur des collections complexes dans de telles situations (transmission à plusieurs reprises).
pour une liaison bidirectionnelle, vous devez utiliser le modificateur .sync
<child :myprop.sync="text"></child>
et vous devez utiliser la propriété watch dans le composant enfant pour écouter et mettre à jour les modifications.
props: ['myprop'],
watch: {
myprop: function(newVal, oldVal) { // watch it
console.log('Prop changed: ', newVal, ' | was: ', oldVal)
}
}
Je travaille avec une propriété calculée comme:
items:{
get(){
return this.resources;
},
set(v){
this.$emit("update:resources", v)
}
},
Ressources est dans ce cas une propriété:
props: [ 'resources' ]
Vous pouvez utiliser le mode veille pour détecter les modifications:
Tout faire au niveau atomique. Donc, vérifiez d’abord si la méthode de surveillance elle-même est appelée ou non en consolant quelque chose à l’intérieur. Une fois que la surveillance a été établie, écrasez-la avec votre logique métier.
watch: {
myProp: function() {
console.log('Prop changed')
}
}