【问题标题】:Child component emit to parent and parent update all children components子组件向父组件发出,父组件更新所有子组件
【发布时间】:2017-07-12 16:35:12
【问题描述】:

我正在尝试使用 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 值?我可以为此使用道具吗?

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

【问题讨论】:

  • 是的,您可以通过 props 控制它,也可以为此探索一些状态管理,例如 vuex

标签: javascript vuejs2 vue.js


【解决方案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 这取决于你想如何构建你的应用程序,父母是否需要知道孩子是否展开?
    猜你喜欢
    • 2018-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-20
    • 2019-03-11
    • 2021-02-12
    • 2021-07-26
    • 2022-01-13
    相关资源
    最近更新 更多