Je suis un peu confus sur la façon de changer les propriétés à l'intérieur des composants, disons que j'ai le composant suivant:
{
props: {
visible: {
type: Boolean,
default: true
}
},
methods: {
hide() {
this.visible = false;
}
}
}
Bien que cela fonctionne, cela donnerait l'avertissement suivant:
Évitez de muter directement un accessoire, car la valeur sera écrasée à chaque nouvelle restitution du composant parent. Utilisez plutôt une propriété data ou calculée en fonction de la valeur de l'accessoire. Prop étant muté: "visible" (trouvé dans le composant)
Maintenant, je me demande quel est le meilleur moyen de gérer cela. De toute évidence, la propriété visible
est transmise lors de la création du composant dans le DOM: <Foo :visible="false"></Foo>
Référencer le code dans votre violon
D'une manière ou d'une autre, vous devriez choisir un lieu pour que l'État vive, pas deux. Je ne sais pas s'il est plus approprié de l'indiquer uniquement dans la variable Alert
ou simplement dans sa parenté, mais vous devriez en choisir une.
Est-ce que le parent ou un composant frère dépend de l'état?
Dans de rares cas, vous voudrez peut-être une combinaison. Peut-être voudrez-vous donner aux parents et à l’enfant la possibilité de cacher l’enfant. Ensuite, vous devriez avoir l'état dans parent et enfant (vous n'avez donc pas à modifier les accessoires de l'enfant dans l'enfant).
Par exemple, enfant peut être visible si: visible && state_visible
, où visible
provient d'accessoires et reflète une valeur dans l'état du parent, et state_visible
correspond à l'état de l'enfant.
Je ne sais pas si c'est le comportement que vous souhaitez, mais voici un violon . J'imagine que vous voulez simplement appeler la toggleAlert
du composant parent lorsque vous cliquez sur l'enfant.
Après avoir lu vos derniers commentaires, il semble que vous ayez le souci de disposer de la logique pour afficher/masquer les alertes sur le parent. Par conséquent, je suggérerais ce qui suit:
parent
# template
<alert :alert-visible="alertVisible"></alert>
# script
data () {
alertVisible: false,
...
},
...
Ensuite, sur l'alerte enfant, vous observerez la valeur de l'accessoire et déplacerez toute la logique dans l'alerte:
enfant (alerte)
# script
data: {
visible: false,
...
},
methods: {
hide () {
this.visible = false
},
show () {
this.visible = true
},
...
},
props: [
'alertVisible',
],
watch: {
alertVisible () {
if (this.alertVisible && !this.visible) this.show()
else if (!this.alertVisible && this.visible) this.hide()
},
...
},
...
Si l'accessoire n'est utile que pour ce composant enfant, donnez à l'enfant une variable prop
telle que initialVisible
et une variable data
telle que mutableVisible
et dans le crochet created
(appelé lorsque la structure de données du composant est assemblée), simplement this.mutableVisible = this.initialVisible
.
Si l'accessoire est partagé par d'autres enfants du composant parent, vous devez en faire la variable data
du parent pour qu'il soit disponible pour tous les enfants. Ensuite, dans l’enfant, this.$emit('visibleChanged', currentVisible)
pour avertir le parent de changer visible
. Dans le modèle parent, utilisez <ThatChild ... :visibleChanged="setVisible" ...>
. Consultez le guide: http://vuejs.org/v2/guide/components.html
Pour aider qui que ce soit, je faisais face au même problème. Je viens de changer ma variable qui se trouvait dans v-model = "" de props array en data. Rappelez-vous la différence entre les accessoires et les données. Dans mon cas, ce n’était pas un problème si vous le changiez, vous devriez peser votre décision.
Par exemple.:
<v-dialog v-model="dialog" fullscreen hide-overlay transition="dialog-bottom-transition">
Avant:
export default {
data: function () {
return {
any-vars: false
}
},
props: {
dialog: false,
notifications: false,
sound: false,
widgets: false
},
methods: {
open: function () {
var vm = this;
vm.dialog = true;
}
}
}
Après:
export default {
data: function () {
return {
dialog: false
}
},
props: {
notifications: false,
sound: false,
widgets: false
},
methods: {
open: function () {
var vm = this;
vm.dialog = true;
}
}
}
Selon le composant Vue.js doc :
Lorsque la propriété parent est mise à jour, elle se répercute sur l'enfant, mais pas l'inverse. Alors, comment pouvons-nous communiquer avec le parent lorsque quelque chose se passe? C’est là que le système d’événements personnalisé de Vue entre en jeu.
Utilisez $emit('my-event)
de l'enfant pour envoyer un événement au parent. Recevez l'événement sur la déclaration enfant à l'intérieur du parent avec v-on:my-event
(ou @my-event
).
Exemple de travail:
// child
Vue.component('child', {
template: '<div><p>Child</p> <button @click="hide">Hide</button></div>',
methods: {
hide () {
this.$emit('child-hide-event')
}
},
})
// parent
new Vue({
el: '#app',
data: {
childVisible: true
},
methods: {
childHide () {
this.childVisible = false
},
childShow () {
this.childVisible = true
}
}
})
.box {
border: solid 1px grey;
padding: 16px;
}
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<div id="app" class="box">
<p>Parent | childVisible: {{ childVisible }}</p>
<button @click="childHide">Hide</button>
<button @click="childShow">Show</button>
<p> </p>
<child @child-hide-event="childHide" v-if="childVisible" class="box"></child>
</div>
Peut-être que cela ressemble à du piratage et viole le concept d'une source de données unique, mais son travail) Cette solution crée une variable proxy locale et hérite des données des accessoires. Prochain travail avec la variable proxy.
Vue.component("vote", {
data: function() {
return {
like_: this.like,
dislike_: this.dislike,
}
},
props: {
like: {
type: [String, Number],
default: 0
},
dislike: {
type: [String, Number],
default: 0
},
item: {
type: Object
}
},
template: '<div class="tm-voteing"><span class="tm-vote tm-vote-like" @click="onVote(item, \'like\')"><span class="fa tm-icon"></span><span class="tm-vote-count">{{like_}}</span></span><span class="tm-vote tm-vote-dislike" @click="onVote(item, \'dislike\')"><span class="fa tm-icon"></span><span class="tm-vote-count">{{dislike_}}</span></span></div>',
methods: {
onVote: function(data, action) {
var $this = this;
// instead of jquery ajax can be axios or vue-resource
$.ajax({
method: "POST",
url: "/api/vote/vote",
data: {id: data.id, action: action},
success: function(response) {
if(response.status === "insert") {
$this[action + "_"] = Number($this[action + "_"]) + 1;
} else {
$this[action + "_"] = Number($this[action + "_"]) - 1;
}
},
error: function(response) {
console.error(response);
}
});
}
}
});
utiliser le composant et passer les accessoires
<vote :like="item.vote_like" :dislike="item.vote_dislike" :item="item"></vote>