【问题标题】:Why isn't the prop reactive in the dynamic component?为什么 prop 在动态组件中没有反应性?
【发布时间】:2019-07-04 08:35:22
【问题描述】:

我有一个动态组件被注入到另一个组件的插槽中,我将 props 对象传递给它。但是当我更新与道具(dataT: this.tableData)关联的数据(数组)时,该道具不会在组件内更新。

似乎我处理了两个不同的对象,但数组是通过引用传递的,不是吗?

这是主要组件


    <template>
       <Button @click="addWindows"></Button>
       <Window v-for="window in windows" :key="window.id">
          <component :is="window.name" v-bind="window.props" @onDeleteRow="handleDeleteRow"></component>    
       </Window>
    </template>


    <script>
        export default{
           data(){
              return{
                 windows:[],
                 tableData:[
                    {
                       id: '0',
                       name: 'dog'
                    },
                    {
                       id: '1',
                       name: 'cow'
                    },
                    {
                       id: '2',
                       name: 'cat'
                    }
                 ]
              }
           },  
           methods:{
              addWindows(){
                 this.windows = [
                 {
                    id: 0,
                    name: 'Component1',
                    props: {
                       dataT: this.tableData
                    }
                 }, 
                 {
                    id: 1,
                    name: 'Component2',
                    props: {}
                 }];
              },
              handleDeleteRow(id){
                 this.tableData = this.tableData.filter(r => r.id != id);
              }
           }
        }
    </script>

当我在主组件中修改this.tableData 时,我希望更新Component1 中的dataT 属性。

【问题讨论】:

    标签: javascript vue.js vue-component


    【解决方案1】:

    基于问题早期版本的原始答案

    如果您将windows 设为计算属性,则它可以依赖于tableData

    export default {
      data() {
        return {
          tableData: [
            {
              id: '0',
              name: 'dog'
            },
            {
              id: '1',
              name: 'cow'
            },
            {
              id: '2',
              name: 'cat'
            }
          ]
        }
      },
      computed: {
        windows () {
          return [
            {
              id: 0,
              name: 'Component1',
              props: {
                dataT: this.tableData
              }
            }, {
              id: 1,
              name: 'Component2',
              props: {}
            }
          ]
        }
      }
    }
    

    如果您不能将其全部设为计算属性,例如因为您需要能够修改它,然后将其保留为 data 并使用计算属性来创建模板中所需的数组。在这种情况下,计算属性只是将数据的不同部分合并为正确的形式。

    在您的原始代码中,dataT: this.tableData 行将不起作用,因为 this.tableData 尚不存在,它只是 undefined。这里没有惰性求值,它需要在到达那条线时解析为正确的对象。

    即使它能够访问正确的对象也无济于事,因为在handleDeleteRow 中,您正在重新分配tableData 以指向不同的对象。传递“按引用”与您用来标识对象的名称无关,它指的是内存中的引用。

    顺便说一句,v-on 也支持对象语法,就像 v-bind 一样,因此您可以以类似的方式将 onDeleteRow 设为可选。

    根据修改后的问题更新

    当你在addWindows写这篇文章时:

    props: {
        dataT: this.tableData
    }
    

    这会将this.tableData当前 值分配给dataT。该当前值将是一个数组,并且由于数组是引用类型,因此对该数组所做的任何修改都将适用,无论使用什么标识符来引用它。

    但是,这一行……​​

    this.tableData = this.tableData.filter(r => r.id != id);
    

    ... 不会修改该数组。相反,它将一个全新的数组分配给this.tableData。这对dataT 引用的数组没有影响,它没有改变。

    有几种方法可以解决这个问题,包括使用计算属性。但是,属性 getter 可能会提供一种方便的技巧:

    addWindows () {
      const vm = this;
    
      this.windows = [
        {
          id: 0,
          name: 'Component1',
          props: {
            get dataT () {
              return vm.tableData
            }
          }
        },
        {
          id: 1,
          name: 'Component2',
          props: {}
        }
      ];
    }
    

    这将始终计算为tableData 的当前值。 Vue 的反应性应该与这个额外的间接有关,它只是认为它等同于直接访问 tableData

    【讨论】:

    • 是的,我知道,实际上windows 最初是空数组,我通过单击按钮填充它,我只是决定简化代码。我会根据您的建议更新代码,以免误导他人,但不幸的是它并不能解决绑定的主要问题
    • 已更新代码。你有什么想法可以解决这个问题吗?
    • @DenisLolik 我已经更新了我的答案以反映新问题
    【解决方案2】:

    TL;DR

    问题在于您的绑定。使用以下内容:

    <component 
        :is="window.name"
        :dataT="window.props.dataT"
        @onDeleteRow="handleDeleteRow">
    </component>
    

    说明

    v-bind 属性指定什么 prop 绑定到什么值(或引用)。在您的情况下,您没有指定要绑定到哪些道具的值,因此组件道具未按预期绑定。

    【讨论】:

    • 谢谢,但是如果应该注入的 ```Component2`` 也有完全不同的 props 怎么办。我不想列出所有的 props,因为它们中的一部分没有引用使用的任何组件。
    • 在这种情况下,你可以传递一个props 道具(你明白我的意思吗?)。子组件将销毁道具并通过自定义验证器进行验证。
    • @Aviad OP只是使用v-bind的对象形式。写v-bind="obj" 完全有效,见vuejs.org/v2/api/#v-bind
    • @Aviad 我明白你的意思,但也许还有另一种更优雅的方法
    猜你喜欢
    • 2020-11-12
    • 2018-12-20
    • 1970-01-01
    • 1970-01-01
    • 2017-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-25
    相关资源
    最近更新 更多