[英]How to call function on child component on parent events
在 Vue 2.0 中,文档和其他文档清楚地表明,父母与孩子之间的交流是通过 props 发生的。
父母如何通过道具告诉孩子事件发生了?
我应该只看一个叫做事件的道具吗? 这感觉不对,替代方案也不对( $emit
/ $on
用于子到父,集线器模型用于远距离元素)。
我有一个父容器,它需要告诉它的子容器可以在 API 上执行某些操作。 我需要能够触发功能。
给子组件一个ref
并使用$refs
直接调用子组件上的方法。
html:
<div id="app">
<child-component ref="childComponent"></child-component>
<button @click="click">Click</button>
</div>
javascript:
var ChildComponent = {
template: '<div>{{value}}</div>',
data: function () {
return {
value: 0
};
},
methods: {
setValue: function(value) {
this.value = value;
}
}
}
new Vue({
el: '#app',
components: {
'child-component': ChildComponent
},
methods: {
click: function() {
this.$refs.childComponent.setValue(2.0);
}
}
})
有关更多信息,请参阅refs 上的 Vue 文档。
您所描述的是父母的状态变化。 您通过道具将其传递给孩子。 正如你所建议的,你会watch
那个道具。 当孩子采取行动时,它会通过emit
通知父母,然后父母可能会再次改变状态。
var Child = { template: '<div>{{counter}}</div>', props: ['canI'], data: function () { return { counter: 0 }; }, watch: { canI: function () { if (this.canI) { ++this.counter; this.$emit('increment'); } } } } new Vue({ el: '#app', components: { 'my-component': Child }, data: { childState: false }, methods: { permitChild: function () { this.childState = true; }, lockChild: function () { this.childState = false; } } })
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.js"></script> <div id="app"> <my-component :can-I="childState" v-on:increment="lockChild"></my-component> <button @click="permitChild">Go</button> </div>
如果你真的想将事件传递给孩子,你可以通过创建一个总线(它只是一个 Vue 实例)并将其作为 prop 传递给孩子来做到这一点。
您可以使用$emit
和$on
。 使用@RoyJ 代码:
html:
<div id="app">
<my-component></my-component>
<button @click="click">Click</button>
</div>
javascript:
var Child = {
template: '<div>{{value}}</div>',
data: function () {
return {
value: 0
};
},
methods: {
setValue: function(value) {
this.value = value;
}
},
created: function() {
this.$parent.$on('update', this.setValue);
}
}
new Vue({
el: '#app',
components: {
'my-component': Child
},
methods: {
click: function() {
this.$emit('update', 7);
}
}
})
运行示例: https ://jsfiddle.net/rjurado/m2spy60r/1/
在子组件上调用方法的简单解耦方式是从子组件发出处理程序,然后从父组件调用它。
var Child = { template: '<div>{{value}}</div>', data: function () { return { value: 0 }; }, methods: { setValue(value) { this.value = value; } }, created() { this.$emit('handler', this.setValue); } } new Vue({ el: '#app', components: { 'my-component': Child }, methods: { setValueHandler(fn) { this.setter = fn }, click() { this.setter(70) } } })
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script> <div id="app"> <my-component @handler="setValueHandler"></my-component> <button @click="click">Click</button> </div>
父进程跟踪子处理函数并在必要时调用。
不喜欢在create
期间在孩子中使用$on
绑定的事件总线方法。 为什么? 随后的create
调用(我正在使用vue-router
)不止一次绑定消息处理程序——导致每条消息有多个响应。
将 props 从 parent 传递给 child 并在 child 中放置 property watcher 的正统解决方案效果更好一些。 唯一的问题是孩子只能对价值转变采取行动。 多次传递相同的消息需要某种簿记来强制转换,以便孩子可以接受更改。
我发现如果我将消息包装在一个数组中,它总是会触发子观察者——即使值保持不变。
家长:
{
data: function() {
msgChild: null,
},
methods: {
mMessageDoIt: function() {
this.msgChild = ['doIt'];
}
}
...
}
孩子:
{
props: ['msgChild'],
watch: {
'msgChild': function(arMsg) {
console.log(arMsg[0]);
}
}
}
HTML:
<parent>
<child v-bind="{ 'msgChild': msgChild }"></child>
</parent>
如果你有时间,可以使用 Vuex 存储来观察变量(又名状态)或直接触发(又名调度)一个动作。
下面的例子是自我解释的。 其中 refs 和 events 可用于在父子之间调用函数。
// PARENT
<template>
<parent>
<child
@onChange="childCallBack"
ref="childRef"
:data="moduleData"
/>
<button @click="callChild">Call Method in child</button>
</parent>
</template>
<script>
export default {
methods: {
callChild() {
this.$refs.childRef.childMethod('Hi from parent');
},
childCallBack(message) {
console.log('message from child', message);
}
}
};
</script>
// CHILD
<template>
<child>
<button @click="callParent">Call Parent</button>
</child>
</template>
<script>
export default {
methods: {
callParent() {
this.$emit('onChange', 'hi from child');
},
childMethod(message) {
console.log('message from parent', message);
}
}
}
</script>
在父组件中调用子组件
<component :is="my_component" ref="my_comp"></component>
<v-btn @click="$refs.my_comp.alertme"></v-btn>
在子组件中
mycomp.vue
methods:{
alertme(){
alert("alert")
}
}
我认为我们应该考虑一下 parent 使用 child 的方法的必要性。实际上,父母不必关心 child 的方法,而是可以将 child 组件视为 FSA(finite state machine)。Parents 组件控制子组件的状态。所以观察状态变化或只使用计算功能的解决方案就足够了
您可以使用mixin设置共享数据属性。 在父级中对其进行更改,在子级中对其进行监视:
// mixin
export default {
data() {
return {
clicked: false
}
}
}
// parent
export default {
mixins: [myMixin],
methods: {
btnClick() {
this.clicked = true
}
}
}
// child
export default {
mixins: [myMixin],
watch: {
clicked(val) {
if(val) {
// yay
}
}
}
}
您可以使用 key 使用 key 重新加载子组件
<component :is="child1" :filter="filter" :key="componentKey"></component>
如果要使用新过滤器重新加载组件,如果单击按钮过滤子组件
reloadData() {
this.filter = ['filter1','filter2']
this.componentKey += 1;
},
并使用过滤器触发功能
您可以通过切换父级中的布尔属性来模拟向子级发送事件。
父代码:
...
<child :event="event">
...
export default {
data() {
event: false
},
methods: {
simulateEmitEventToChild() {
this.event = !this.event;
},
handleExample() {
this.simulateEmitEventToChild();
}
}
}
子代码:
export default {
props: {
event: {
type: Boolean
}
},
watch: {
event: function(value) {
console.log("parent event");
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.