我有一个嵌套的组件,子组件应从主实例中接收一个参数,但问题是我必须调用事件两倍的获取参数。
index.html
<div id="app">
<button @click="displayComponent">Display</button><br/><hr/>
{{ message }}
<mycomponent v-if="showComponent" @hide="hideComponents"></mycomponent>
</div>
code.js
window.bus = new Vue();
Vue.component('mycomponent', {
template: `
<div>
<h3>Im the parent component</h3>
<childcomponent></childcomponent>
<button @click="$emit('hide')">Hide components</button>
</div>
`
});
Vue.component('childcomponent', {
template:`
<div>
<h4>Im the child component</h4>
<p>{{ data }}</p>
</div>
`,
data() {
return {
text: 'Nothing loaded'
};
},
methods: {
test() {
alert('hello');
},
getData(x) {
this.text = x;
}
},
created(){
bus.$on('extraCall', data => {
this.getData(data);
this.test();
});
}
});
const app = new Vue({
el: '#app',
data: {
message: 'hello world!',
showComponent: false
},
methods: {
displayComponent() {
bus.$emit('extraCall', 'this is some extra text');
this.showComponent = true;
},
hideComponents() {
this.showComponent=false;
}
}
});
单击"显示"按钮后,子组件元素内部的文本值设置为默认值,它将用extraCall
事件触发bus.$emit
,并以某些文本为参数,这应更新文本值,并且仅在之后发生。第二次单击"显示"按钮。
我缺少什么?
<mycomponent>
(及其子女<childcomponent>
)在单击显示按钮时未实例化,因为v-if="showComponent"
。
第一次点击:
-
extraCall
在公共汽车上排放,但没有对该事件的听众忽略。 -
<mycomponent>
将showComponent
设置为true。 -
<mycomponent>
在其created
钩中注册extraCall
事件的听众。
第二次点击:
-
extraCall
在公共汽车上排放,<mycomponent>
处理它。
您可能会认为bus.$emit()
和this.showComponent = true
行应该交换,以便在发出事件之前 <mycomponent>
在上进行实例化,但这仍然行不通,因为Vue违背了下一个组件的创建,直到下一个组件的创建当视图更新时,Microtask。
这可能有效:
displayComponent() {
this.showComponent = true;
// Wait for child component to be instantiated
this.$nextTick(() => {
bus.$emit('extraCall', 'this is some extra text');
});
}
如果以上代码对您有用,但是我仍然不推荐它。在发布事件之前,您不需要考虑孩子组件的创建(将您的组件融在一起)。您应该以其他方式共享数据,请检查其他问题,以了解与组件共享数据的最佳方法。