子组件发送到父级和父级更新所有子组件

时间:2017-02-22 14:46:07

标签: javascript vuejs2 vue.js

我尝试使用vue js 2创建一个包含可展开项目的列表。我的想法是,当我点击一个项目时,我希望它展开(显示它的内容),如果它是'尚未展开并关闭所有其他扩展元素。我创建了两个组件expandable-panelexpandable-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值?我可以为此使用道具吗?

现在,它会切换每个元素,但我无法更新其他元素。 谢谢

2 个答案:

答案 0 :(得分: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/

答案 1 :(得分:0)

ExpandablePanel组件中:您应该只有@expand,因为这是您从孩子那里发出的:

<template>
    <div class="expandable-panel" @expand="doStuff">
        <slot></slot>
    </div>
</template>