【问题标题】:Pass properties from parent component to all transcluded children component in Vue将属性从父组件传递给 Vue 中所有被转入的子组件
【发布时间】:2017-01-19 17:16:47
【问题描述】:

我想将一些属性从父级传递给他的所有子级,当它们被嵌入时(内容分发语法)。在这种情况下,父母不知道(据我所知)他的孩子,所以我不知道如何继续。

更具体地说,我想要一种写法:

<my-parent prop1="foo" prop2="bar">
    <my-children></my-children> <!-- Must know content of prop1 and prop2 -->
    <my-children></my-children> <!-- Must know content of prop1 and prop2 -->
</my-parent>

不必写这个:

<my-parent prop1="foo" prop2="bar">
    <my-children prop1="foo" prop2="bar"></my-children>
    <my-children prop1="foo" prop2="bar"></my-children>
</my-parent>

有可能吗?谢谢。

【问题讨论】:

  • 你考虑过 vuex 吗?
  • @AldoRomo88 请不要,我只想将一个愚蠢的参数传递给所有孩子,而不是管理完整的 Redux 状态。另外,这是针对可重用组件的,所以依赖越少越好。

标签: javascript vue.js vue-component


【解决方案1】:

Props 只允许数据流一层。如果你想永久保存数据,你可以使用事件总线。

在你的主文件中用一个空的 Vue 实例实例化一个事件总线。

var bus = new Vue();

然后在您的父级中,使用要传递的数据发出事件

 bus.$emit('myEvent', dataToBePassed);

在您想获取数据的任何地方收听myEvent。在您的情况下,它是在您的子组件中完成的

bus.$on('myEvent', function(data) {
     .....
});

【讨论】:

    【解决方案2】:

    在这一点上(我不是 vue 专家)我只能考虑这个解决方案。

    分配每个组件的道具很无聊,我同意,那么为什么不以编程方式进行呢?

    // Create a global mixin
    Vue.mixin({
      mounted() { // each component will execute this function after mounted
        if (!this.$children) {
          return;
        }
    
        for (const child of this.$children) { // iterate each child component
          if (child.$options._propKeys) {
            for (const propKey of child.$options._propKeys) { // iterate each child's props
              // if current component has a property named equal to child prop key
              if (Object.prototype.hasOwnProperty.call(this, propKey)) {
                // update child prop value
                this.$set(child, propKey, this[propKey]);
    
                // create a watch to update value again every time that parent property changes
                this.$watch(propKey, (newValue) => {
                  this.$set(child, propKey, newValue);
                });
              }
            }
          }
        }
      },
    });
    

    这可行,但您会收到一条丑陋的 vue 警告消息:

    [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value.
    

    我不确定这是否是一个好的解决方案,但它确实有效,所以如果您决定使用,请记住 Global-Mixin 建议:

    谨慎使用全局混合,因为它会影响每个 创建的单个 Vue 实例,包括第三方组件。

    请在https://github.com/aldoromo88/PropsConvention查看完整示例

    希望对你有帮助

    【讨论】:

    • 感谢您的回答:我遇到了一些看起来像那样的事情,但是警告和明确观看每个道具的需要对我来说有点反感。我还将根据逆向方法提交我自己的解决方案。
    【解决方案3】:

    这是我的解决方案,这可能不是什么大问题,但这是我现在想做的最干净的解决方案。原则是创建计算属性,如果它们存在,将使用自己的组件属性,否则获取 $parent 值。然后可以在 this._prop 中访问真正的道具。

    Vue.component('my-children', {
        props: ["prop1", "prop2"],
        template: "<div>{{_prop1}} - {{_prop2}}</div>",
        computed: {
            _prop1: function() {
                return this.prop1 || this.$parent.prop1;
            },
            _prop2: function() {
                return this.prop2 || this.$parent.prop2;
            }
        }
    });
    

    这是一个混合生成器,它以更优雅的方式执行此操作,并且可能具有多个级别:

    function passDown(...passDownProperties) {
        const computed = {};
        passDownProperties.forEach((prop) => {
            computed["_" + prop] = function() {
                return this[prop] || this.$parent[prop] || this.$parent["_" + prop];
            };
        });
        return { computed };
    }
    
    Vue.component('my-children', {
        props: ["prop1", "prop2"],
        template: "<div>{{_prop1}} - {{_prop2}}</div>",
        mixins: [passDown("prop1", "prop2")]
    });
    

    【讨论】:

    • 我喜欢它!,你的解决方案比我的更干净,效果很好
    猜你喜欢
    • 1970-01-01
    • 2020-04-18
    • 1970-01-01
    • 2019-11-12
    • 1970-01-01
    • 2017-12-02
    • 2020-02-04
    • 2018-08-03
    • 2020-07-26
    相关资源
    最近更新 更多