私はvueアプリケーションを使用しています:
コンポーネントの子で構成されるコンポーネントの親コンポーネント
コンポーネントの親の内部にボタンがあり、誰かがボタンをクリックすると、vueによって処理され、別のコンポーネントに渡されるためにイベントを発行したい
これまでに行ったこと:
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>
Console.log(pty);に到達します。行ですが、this。$ emit( 'itemSelected'は通過しません:
console.log( 'itemSelectedListener'、item); //これは呼び出されません...
ヒント?
child-> parent-> Vue-instanceからイベントをバブルアップする必要がありますか? (私も試してみましたが、成功しませんでした)
複数の子コンポーネントをレンダリングしようとするため、component-parent
テンプレートには1つの問題があります。 Vueは通常、コンポーネント内に単一のルートdivを必要とするため、divまたはその他のタグでラップする必要があります。
<div>
<component-child v-for="q in items"></component-child>
</div>
2番目に指摘することは、2レベル下の子コンポーネントからイベントを発行し、ルートでそれをリッスンすることです。
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
ここには2つのオプションがあります。 component-child
から発信するか、component-parent
でもそれをリッスンしてから、さらに上に伝搬します。 Fiddle https://jsfiddle.net/bjqwh74t/29/
2番目のオプションは、空のvueインスタンスであるbus
と呼ばれるグローバルを登録することです。これは、子と親以外のコンポーネント間の通信が必要な場合に使用できます。 Fiddle https://jsfiddle.net/bjqwh74t/30/
通常、親コンポーネントと子コンポーネント間では、v-on:event-name="handler"
を使用して子から発信し、親でリッスンすることでイベントを直接使用しますが、コンポーネント間により多くのレベルがある場合は、2番目のアプローチを使用します。
最初のケースのドキュメントリンク: https://vuejs.org/v2/guide/components.html#Using-v-on-with-Custom-Events
2番目のケースのドキュメントリンク: https://vuejs.org/v2/guide/components.html#Non-Parent-Child-Communication
PS:イベント名にkebab-caseを使用することをお勧めします。つまり、大文字ではなく-
で記述します。大文字で書くと、イベントがルートで捕捉されないという奇妙な状況になる可能性があります。
価値があるものについては、ブラウザのイベントAPIを使用できます。 Vueの組み込みのものよりも少しスクリプティングが必要ですが、これらのバブルの問題を回避することもできます(受け入れられた答えのように、「バス」を作成するのとほぼ同じ量のコードです)。
子コンポーネント:
this.$el.dispatchEvent(new CustomEvent('itemSelected', { detail: { 'priority' : pty }, bubbles: true, composed: true });
親コンポーネントのmounted
ライフサイクル部分:
mounted() {
this.$el.addListener('itemSelected', e => console.log('itemSelectedListener', e.detail));
}
それは少し遅れていますが、ここに私がそれをした方法があります:
コンポーネントの子:
this.$root.$emit('foobar',{...});
コンポーネント親:
this.$root.$on('foobar')
子コンポーネントでは、単に$emit
にイベントを送信する$root
このような:
v-on:click="$root.$emit('hamburger-click')"
次に、親コンポーネント(例:「App」)で、次のようにVue mounted
ライフサイクルフックにリスナーを設定します。
export default {
<snip...>
mounted: function() {
this.$root.$on('hamburger-click', function() {
console.log(`Hamburger clicked!`);
});
}
}