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 可拖动子组件修改父数据的主要内容,如果未能解决你的问题,请参考以下文章