Je suis assez nouveau sur Vue.js et j'utilise la syntaxe ES6 avec vue-class-component
. J'ai un problème en essayant d'émettre un événement d'un enfant à son parent.
J'ai suivi la logique de la syntaxe Vue.js par défaut mais je n'arrive pas à faire en sorte que mon parent intercepte un événement émis par l'enfant. Code:
Composant enfant
J'ai joint un écouteur d'événements Click à chaque <li>
, qui appelle une fonction qui émet un événement. L'écouteur d'événements est défini sur le parent.
export default class HorizontalNavigation {
handleClick (e) {
e.preventDefault();
// console.log(e.target.dataset.section);
this.$emit('ChangeView', e.target.dataset.section);
}
render (h) {
return (
<div class={ style.horizontalNavigation } >
<div class='sections-wrapper'>
<div class={ style.sections }>
<ol>
<li><a on-click={ this.handleClick } href='#1' data-section='1' class='selected'>We are</a></li>
<li><a on-click={ this.handleClick } href='#2' data-section='2'>Services</a></li>
<li><a on-click={ this.handleClick } href='#3' data-section='3'>Cases</a></li>
<li><a on-click={ this.handleClick } href='#4' data-section='4'>Studio</a></li>
<li><a on-click={ this.handleClick } href='#5' data-section='5'>Career</a></li>
<li><a on-click={ this.handleClick } href='#6' data-section='6'>Contact</a></li>
</ol>
<span class='filling-line' aria-hidden='true'></span>
</div>
</div>
</div>
);
}
}
Composant parent
export default class ViewsContainer {
ChangeView (data) {
console.log(data);
}
render (h) {
return (
<div class={ style.restrictOverflow } >
<HorizontalNavigation />
<main class={ style.viewsContainer } on-ChangeView={ this.ChangeView } >
<SingleView dataSection='weare' id='1' class='selected' />
<SingleView dataSection='services' id='2' />
<SingleView dataSection='cases' id='3' />
<SingleView dataSection='studio' id='4' />
<SingleView dataSection='career' id='5' />
<SingleView dataSection='contact' id='6' />
</main>
</div>
);
}
}
En suivant la syntaxe vue.js, je devrais être capable d'écouter l'événement enfant du parent, en émettant l'événement depuis l'élément, mais le parent ne semble pas attraper l'événement.
Où vais-je mal?
Tu dois $emit
sur le modèle d'affichage que vous souhaitez recevoir votre $emit
, utilisez un bus
ou utilisez https://vuex.vuejs.org/en/intro.html .
La manière la plus simple est de simplement $emit
de l'enfant directement au composant parent:
this.$parent.$emit('ChangeView', e.target.dataset.section);
C'est [~ # ~] ok [~ # ~] , mais si vous avez une longue chaîne de composants, vous devez $emit
pour chaque $parent
dans la chaîne.
Vous pouvez utiliser Vue pour créer un bus d'événements global très simplement. Vous créez une instance de Vue dans votre composant principal, puis tous les autres composants de votre application peuvent emit
événements et utilisez on
pour réagir à ces événements.
var bus = new Vue({});
var vm = new Vue({
methods: {
changeView() {
bus.$emit('ChangeView', e.target.dataset.section);
}
});
Il est également possible d'émettre vers $root
mais ce n'est pas recommandé. Cependant, si votre app
devient assez complexe, vous pouvez envisager d'utiliser à la place le système de gestion d'état de Vues, vuex .
Vous pouvez écouter le $emit
dans le viewmodel en utilisant $on
et à l'écoute de l'événement spécifique:
var vm = new Vue({
created() {
this.$on('ChangeView', section => {
console.log(section);
});
}
);
Ce serait également similaire si vous utilisiez le bus, mais vous référeriez simplement le bus à la place:
bus.$on('ChangeView, ...);
Et vous pouvez également l'utiliser directement dans votre html en utilisant v-on
:
<div v-on:ChangeView="doSomething"></div>
Sauf si je manque quelque chose (très probablement), dans un exemple simple comme celui-ci, il vous suffit d'écouter l'événement emit
ted dans votre composant. Par exemple, dans votre élément parent, vous auriez:
<HorizontalNavigation v-on:ChangeView={this.ChangeView} />
Ensuite, dans votre composant enfant (HorizontalNavigation
), vous feriez emit
l'événement 'ChangeView':
this.$emit('ChangeView', e.target.dataset.section);
J'ai moi-même essayé cela dans un code similaire, basé sur un commentaire que vous avez fait sur la réponse de @ craig_h, et c'était ce dont j'avais besoin. Je n'avais pas besoin de emit
pour être parent, ou utiliser un bus, ou vuex.
Dans Vue, vous pouvez communiquer depuis les enfants jusqu'aux composants parents en en émettant des événements . Le composant enfant 'émet' un événement avec $emit
& le composant parent l'écoute comme ceci:
Composant enfant:
<template>
<div>
<button @click="this.handleClick">Click me!</button>
</div>
</template>
<script>
export default {
name: "BaseButton",
methods: {
handleClick: function() {
this.$emit("clickFromChildComponent");
}
}
};
</script>
<style scoped>
</style>
Composant parent:
<template>
<div class="home">
<h1>Passing a event from child up to parent!</h1>
<BaseButton @clickFromChildComponent="handleClickInParent"/>
</div>
</template>
<script>
import BaseButton from "./BaseButton";
export default {
components: {
BaseButton
},
name: "Home",
methods: {
handleClickInParent: function() {
alert('Event accessed from parent!');
}
}
};
</script>
<style scoped>
</style>
Vous pouvez trouver un exemple d'implémentation de code de travailici et l'utiliser dans votre propre contexte .