Vue 可拖动子组件修改父数据

Posted

技术标签:

【中文标题】Vue 可拖动子组件修改父数据【英文标题】:Vue Draggable child components modifying parent data 【发布时间】:2021-03-08 12:24:49 【问题描述】:

我的应用程序结构看起来像这样

App
    Column Component
        Task Component
        Task Component
        Task Component
    Column Component
        Task Component
        Task Component
    Column Component
    Column Component

每一列都有一个围绕任务的<draggable> 组件。 在应用程序级别,我有一个数据对象,其中包含不同的列,每列都有其任务。

data: function() 
    return 
        columns: 
            new: [
                
                    ID: 1,
                    title: 'The thing',
                    description: 'Prepare a proposal for facade'
                ,
                
                    ID: 2,
                    title: 'The thing 2',
                    description: 'Prepare a proposal for facade'
                ,
                
                    ID: 3,
                    title: 'The thing 3',
                    description: 'Prepare a proposal for facade'
                
            ],
            inProgress: [
                
                    ID: 4,
                    title: 'The thing 4',
                    description: 'Prepare a proposal for facade Store Opening Process (DEMO)'
                ,
                
                    ID: 5,
                    title: 'The thing 5',
                    description: 'Prepare a proposal for facade Store Opening Process (DEMO)'
                
            ],
            done: [],
            onHold: []
        
    

我遍历列,并将对象绑定到组件:

<kool-column
    v-for="column"
    v-bind="colum"
></kool-column>

Kool Column 组件:

<script id="kool-column-template" type="text/x-template">
    <div>
        <div>
             column.name  ( column.cards.length )
        </div>
        <div>
            <draggable v-model="cards" group="columnkool">
                <div v-for="card in cards" :key="card.ID">
                    <kool-card v-bind="card"></kool-card>
                </div>
            </draggable>
        </div>
    </div>
</script>

<script>
    $(document).ready(function() 
        Vue.component('koolColumn', 
            template: '#kool-column-template',
            props: 
                ID: 
                    type: Number,
                    required: true
                ,
                name: 
                    type: String,
                    required: true
                ,
                cards: 
                    type: Array,
                    default: function()  return []; 
                
            
        );
    );
</script>

所以,我的问题是,当我拖放卡片时,出现 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. Prop being mutated: "cards"

有道理,我一直在阅读和调查,在 Vue 中,您想使用 props 将数据向下传递到组件中,但是为了修改这些数据,您向父级发送一个事件,并让父级修改它。

好的,但是我使用的库Vue Draggable 修改了我通过它的列表。所以我该怎么做? 我想到的解决方案:

    在挂载列组件时,将道具卡复制到组件的数据中,用于列表和修改,每次更改时,将新列表发送给父级。我认为这没有多大意义,我会有两个信息来源(app对象中的卡片和我的列组件对象中的卡片),并且存在它们未对齐的风险,毕竟我正在更新列表分开。 当放置一个项目时,使用库实际上“不允许”放置,(您可以使用库事件并返回 false,因此它实际上不会更改列表)。捕捉事件,将拖动的项目的信息发送给父级,用户是否试图放下它并相应地更改数据。基本上,我会使用拖放库来了解用户试图将某些东西放在哪里,并实际手动更改数据。这看起来也很奇怪,代码真的很难理解,并且在放下物品时会闪烁(因为它会回到原来的位置,然后回到你想要的位置)。 另一个不好的解决方案是传递给列组件,而不是单独的 v-bind 和每个属性,而是整个对象。因此,我使用:column="column" 而不是v-bind="colum",这实际上使Vue 警告消失并保持双重数据绑定。问题是,我正在做反模式,没有警告,但仍然......(顺便说一句,这种方法来自这个例子:Task management using Vue)

我应该继续使用方法 #2 吗?虽然丑陋,但至少不是反模式,也不会使信息翻倍。或者当我不在“控制”正在更新的列表时,是否有另一种保持双重数据绑定的方法?或者只是应用的不同架构/结构?

【问题讨论】:

嗨 Joseph,遇到的问题与您的完全相同:我想在子表组件中包含 vue-dragable,我将“行”作为道具传递。我在道具的可变性方面面临同样的问题。您找到问题的答案了吗?你最后做了什么?看起来互联网没有提供很多关于处理子组件内部 vuue-draggable 的好方法的线索 嗨@SebT,我正在做我在帖子中写的解决方案3。 【参考方案1】:

Vue draggable有两种处理提供的数据的方式:

    使用v-model="array",这是不可变的 - 如果项目的顺序发生变化,它会创建一个新副本。 使用:list="array",这使用相同的引用并使用拼接来更新数组。

在你的情况下,使用:list="array",你应该没问题。

【讨论】:

以上是关于Vue 可拖动子组件修改父数据的主要内容,如果未能解决你的问题,请参考以下文章

vue2.0子组件能不能修改父组件传递过来的数据

vue 父组件传数组或对象给子组件时 子组件修改值父组件也会做相应修改

vue子组件如何修改父组件data里的值

vue中父组件如何动态修改子组件的值?

React父传子和子组件触发修改父组件修改数据

vue子组件给父组件传属性