Структура моих приложений выглядит примерно так
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 вы хотите использовать реквизиты для передачи данных в компоненты, но затем, чтобы изменить эти данные, вы отправляете событие родителю и позволяете родителю изменять его.
Хорошо, но библиотека, которую я использую, Vue Draggable изменяет список, который я ей передаю. Так что я должен делать? Решения, о которых я думал:
- При монтировании компонента столбца скопируйте карты свойств в данные компонента, используйте их для списка и модификаций, и каждый раз, когда он изменяется, отправляйте родительскому элементу новый список. Я не думаю, что это имеет большой смысл, у меня будет два источника информации (карточки в объекте приложения и карточки в объекте компонента моего столбца), и я рискую, что они не выровнены, в конце концов, я обновляю список раздельно.
- При отбрасывании элемента используйте библиотеку, чтобы фактически не допустить сброса (вы можете использовать события библиотеки и вернуть false, чтобы они фактически не меняли списки). Поймайте событие, отправьте родителю информацию о том, какой элемент был перетащен и пытался ли пользователь отбросить его, и соответствующим образом изменить данные. По сути, я бы использовал библиотеку перетаскивания, чтобы знать, где пользователь пытался что-то бросить, и фактически изменял данные вручную. Это также кажется странным, код действительно сложно уследить, и при падении элемента наблюдается мерцание (потому что он возвращается в исходное положение, а затем в то место, где вы хотели его иметь).
- Еще одно плохое решение - передать компоненту столбца не v-bind и каждое свойство по отдельности, а весь объект. Поэтому вместо
v-bind="colum"
я делаю:column="column"
, что фактически заставляет исчезнуть предупреждение Vue и сохраняет двойную привязку данных. Дело в том, что я использую анти-шаблон без предупреждения, но все же ... (кстати, этот подход исходит из этого примера: Управление задачами с помощью Vue)
Должен ли я продолжить подход №2? Уродливый, но, по крайней мере, не антипаттерн и не дублирующий информацию. Или есть другой способ сохранить двойную привязку данных, когда я не контролирую обновляемый список? Или, может быть, просто другая архитектура / структура для приложения ?.