J'ai mon application vue utilisant:
composant-parent composant composé de composant-enfant
à l'intérieur du composant-parent, j'ai des boutons, quand quelqu'un clique sur un bouton, je veux émettre un événement afin d'être traité par vue et transmis à un autre composant
Ce que j'ai fait jusqu'à présent:
var vm = new Vue({
el: '#app',
methods:{
itemSelectedListener: function(item){
console.log('itemSelectedListener', item);
}
}
});
Vue.component('component-child', {
template: ' <span v-on:click="chooseItem(pty )" >Button </span>'
,
methods: {
chooseItem: function(pty){
console.log(pty);
this.$emit('itemSelected', {
'priority' : pty
});
}
}
});
Vue.component('component-parent', {
template: '<component-child v-for="q in items" ></component-child>'
});
HTML:
<component-parent v-on:itemSelected="itemSelectedListener" ></component-parent>
Il atteint mon console.log (pty); ligne mais il semble que cela. $ emit ('itemSelected' ne passera pas:
console.log ('itemSelectedListener', item); // ça ne va pas s'appeler ...
un indice?
dois-je bouillir l'événement de child-> parent-> Vue-instance? (J'ai aussi essayé ça mais sans succès)
Il existe un problème avec votre modèle component-parent
car il tente de restituer plusieurs composants enfants. Vue nécessite généralement un seul div de racine à l'intérieur des composants. Vous devez donc l'envelopper dans une balise div ou autre.
<div>
<component-child v-for="q in items"></component-child>
</div>
Une deuxième chose à souligner est que vous émettez un événement à partir d'un composant enfant de 2 niveaux et que vous l'écoutez à la racine.
Root //but you listen to the event up here 1 level above
Component 1 //you should listen to the event here
Component 2 //your try to emit it from here
Vous avez 2 options ici. Soit émettre depuis component-child
écoutez cela même dans component-parent
puis propagez cela même vers le haut. Fiddle https://jsfiddle.net/bjqwh74t/29/
La deuxième option consisterait à enregistrer une variable globale appelée bus
, qui est une instance d'affichage vide que vous pouvez utiliser dans de tels cas lorsque vous souhaitez une communication entre des composants non parent-enfant. Fiddle https://jsfiddle.net/bjqwh74t/30/
Généralement, entre les composants parent et enfant, vous utilisez les événements directement en émettant à partir de l'enfant et en écoutant parent avec v-on:event-name="handler"
, mais dans les cas où vous avez plus de niveaux entre les composants, utilisez la deuxième approche.
Lien Doc pour le premier cas: https://vuejs.org/v2/guide/components.html#Using-v-on-with-Custom-Events
Lien Doc pour le deuxième cas: https://vuejs.org/v2/guide/components.html#Non-Parent-Child-Communication
PS: préférez utiliser la casse kebab pour les noms d’événements, c’est-à-dire que vous écrivez avec -
au lieu de majuscules. Écrire avec des majuscules peut donner lieu à des situations étranges où votre événement n’est pas pris au piège.
Pour ce que cela vaut, vous pouvez utiliser l'API d'événements du navigateur. Cela nécessite un peu plus de script que les éléments intégrés de Vue, mais cela vous aide également à résoudre ces problèmes (et correspond à peu près à la même quantité de code que la création d'un "bus", comme dans la réponse acceptée).
Sur la composante enfant:
this.$el.dispatchEvent(new CustomEvent('itemSelected', { detail: { 'priority' : pty }, bubbles: true, composed: true });
Sur le composant parent, dans la partie mounted
cycle de vie:
mounted() {
this.$el.addListener('itemSelected', e => console.log('itemSelectedListener', e.detail));
}
Dans votre composant enfant, utilisez simplement $emit
pour envoyer un événement à $root
comme ceci:
v-on:click="$root.$emit('hamburger-click')"
Ensuite, dans votre composant parent ("App", par exemple), configurez le programme d'écoute dans le hook Vue mounted
lifecycle de la manière suivante:
export default {
<snip...>
mounted: function() {
this.$root.$on('hamburger-click', function() {
console.log(`Hamburger clicked!`);
});
}
}
C'est un peu tard mais voici comment je l'ai fait:
composant-enfant:
this.$root.$emit('foobar',{...});
composant-parent:
this.$root.$on('foobar')