子组件向父组件发出,父组件更新所有子组件
Posted
技术标签:
【中文标题】子组件向父组件发出,父组件更新所有子组件【英文标题】:Child component emit to parent and parent update all children components 【发布时间】:2017-07-12 16:35:12 【问题描述】:我正在尝试使用 vue js 2 创建一个包含可扩展项目的列表。这个想法是,当我单击一个项目时,如果它尚未展开,我希望它展开(显示它的内容)并关闭所有其他展开元素。我创建了两个组件expandable-panel
和expandable-item
。我可以在里面有多种类型的内容,所以我想使用插槽。
我的代码:
ExpandablePanel
组件:
<template>
<div class="expandable-panel" @expanded="doStuff">
<slot></slot>
</div>
</template>
<script type="text/babel">
export default
methods:
doStuff: function()
alert('expanded');
</script>
ExpandableItem
组件:
<template>
<div class="expandable-item" @click="toggleExpand">
<div class="expandable-item-header">
title
</div>
<div class="expandable-item-body" v-if="expanded">
<slot></slot>
</div>
</div>
</template>
<script type="text/babel">
export default
props:
title: String
// expanded:
// type: Boolean,
// default: true
//
,
data: function()
return
expanded: true
,
methods:
toggleExpand: function()
this.expanded = !this.expanded;
this.$emit('expand');
</script>
还有我的 html 文件
<expandable-panel>
<expandable-item title='title 1'>Lorem ipsum...</expandable-item>
<expandable-item title='title 2'>Lorem ipsum...</expandable-item>
<expandable-item title='title 3'>Lorem ipsum...</expandable-item>
</expandable-panel>
我的应用和组件是这样注册的:
Vue.component('expandable-panel', require('./components/global/ExpandablePanel.vue'));
Vue.component('expandable-item', require('./components/global/ExpandableItem.vue'));
const app = new Vue(
el: '#app'
);
问题:
$emit
部分似乎没有到达父组件内的 @expanded="doStuff"
。
即使它到达那里,我如何正确切换 expanded
值?我可以为此使用道具吗?
现在,它会切换每个元素,但我无法更新其他元素。 谢谢
【问题讨论】:
是的,您可以通过 props 控制它,也可以为此探索一些状态管理,例如 vuex。 【参考方案1】:这里有严格的父子关系,所以你可以通过 $parent 对象发出事件。
首先,在创建父对象时,使用this.$on
监听您的事件:
Vue.component('parent',
template: `<div><slot></slot></div>`,
created: function()
this.$on('event', function(message)
alert(message);
)
);
然后在您的子组件内部使用$parent.$emit
发出此事件
Vue.component('child',
template: `<button @click="$parent.$emit('event', 'From child')">I'm slot</button>`
);
这里是工作演示:https://jsfiddle.net/rdjjpc7a/1754/
【讨论】:
【参考方案2】:在ExpandablePanel
组件中:您应该只有@expand
,因为这是您从孩子发出的:
<template>
<div class="expandable-panel" @expand="doStuff">
<slot></slot>
</div>
</template>
【讨论】:
感谢您的回复。我有一个问题。如果doStuff
方法不应该在ExpandablePanel
内部,我应该在哪里定义它?
@NightFall 这取决于你想如何构建你的应用程序,父母是否需要知道孩子是否展开?以上是关于子组件向父组件发出,父组件更新所有子组件的主要内容,如果未能解决你的问题,请参考以下文章