如何在 Vue.js 中保持可排序数组和组件的顺序
How to keep sortable arrays and components in order in Vue.js
我正在使用 Vue.js 和 Dragula 制作拖放磁贴页面。每个图块都包含自己的一组数据,因此每个图块都是一个 Vue 组件。
问题是,一旦我拖放其中一个图块,DOM 元素和 Vue 实例中的数据数组就会不同步并开始出现问题。只是拖放不会产生问题,但是一旦我拖放一些东西然后尝试删除它,一切都会出错。
这里是 fiddle:https://jsfiddle.net/wfjawvnL/13/
这是我的 HTML,带有组件模板:
<body>
<div id="app">
<div id="draggable" class="wrapper">
<template v-for="(index, item) in list">
<block :id="index" :index="index" :item="item" :name="item.name">
</block>
</template>
</div>
<div class="footer">
<pre>{{ $data | json }}</pre>
</div>
</div>
</body>
<template id="block-template">
<div :id="index" :class="[name, 'block']">
<div class="text name">{{ name }}</div>
<div>Index: {{ index }}</div>
<span class="delete" v-on:click="removeItem(item)">✗</span>
</div>
</template>
这是我的 Vue 实例:
var vm = new Vue({
el: '#app',
data: {
list: [
{name: 'item1'},
{name: 'item2'},
{name: 'item3'},
{name: 'item4'},
{name: 'item5'}
]
},
methods: {
reorder: function (element, sibling) {
var children = element.parentNode.querySelectorAll(".block");
var length = this.list.length;
var ids = [];
for (var i = 0; i < length; i++) {
if (children[i].id) {
ids.push(children[i].id);
}
children[i].id = i;
}
var vm = this;
var newArr = ids.map(function (id) {
return vm.list[id];
});
this.list = newArr;
}
}
});
组件如下:
Vue.component('block', {
template: '#block-template',
props: ['index', 'name', 'item'],
methods: {
removeItem: function (item) {
vm.list.$remove(item);
}
}
});
我这样称呼德拉古拉:
dragula([document.getElementById('draggable')]).on('drop', function (el, target, source, sibling) {
vm.reorder(el, sibling);
});
这个 fiddle 工作正常但不使用组件:https://jsfiddle.net/z2s83yfL/1/
我有两个问题。首先,我绑定了数组索引并将其用作 id。索引正在更改,这也导致 id 更改。其次,在模板标签上使用 v-for 会导致一些问题。我将标签更改为 div,现在可以使用了。
工作fiddle:https://jsfiddle.net/wfjawvnL/18/
Vue 内容:
Vue.component('block', {
template: '#block-template',
props: ['name', 'item'],
methods: {
removeItem: function (item) {
vm.list.$remove(item);
}
}
});
var vm = new Vue({
el: '#app',
data: {
list: [
{name: 'item1'},
{name: 'item2'},
{name: 'item3'},
{name: 'item4'},
{name: 'item5'}
]
},
ready: function() {
var self = this;
var from = null;
var drake = dragula([document.querySelector('#draggable')]);
drake.on('drag', function(element, source) {
var index = [].indexOf.call(element.parentNode.children, element);
from = index;
});
drake.on('drop', function(element, target, source, sibling) {
var index = [].indexOf.call(element.parentNode.children, element);
self.list.splice(index, 0, self.list.splice(from, 1)[0]);
});
}
});
HTML 东西:
<body>
<div id="app">
<div id="draggable" class="wrapper">
<div class="wrapper" v-for="item in list">
<block :item="item" :name="item.name">
</block>
</div>
</div>
<pre>{{ $data | json }}</pre>
</div>
</body>
<template id="block-template">
<div :class="[name, 'block']">
<div class="text name" v-on:click="removeItem(item)">{{ name }}</div>
<span class="delete" v-on:click="removeItem(item)">✗</span>
</div>
</template>
我正在使用 Vue.js 和 Dragula 制作拖放磁贴页面。每个图块都包含自己的一组数据,因此每个图块都是一个 Vue 组件。
问题是,一旦我拖放其中一个图块,DOM 元素和 Vue 实例中的数据数组就会不同步并开始出现问题。只是拖放不会产生问题,但是一旦我拖放一些东西然后尝试删除它,一切都会出错。
这里是 fiddle:https://jsfiddle.net/wfjawvnL/13/
这是我的 HTML,带有组件模板:
<body>
<div id="app">
<div id="draggable" class="wrapper">
<template v-for="(index, item) in list">
<block :id="index" :index="index" :item="item" :name="item.name">
</block>
</template>
</div>
<div class="footer">
<pre>{{ $data | json }}</pre>
</div>
</div>
</body>
<template id="block-template">
<div :id="index" :class="[name, 'block']">
<div class="text name">{{ name }}</div>
<div>Index: {{ index }}</div>
<span class="delete" v-on:click="removeItem(item)">✗</span>
</div>
</template>
这是我的 Vue 实例:
var vm = new Vue({
el: '#app',
data: {
list: [
{name: 'item1'},
{name: 'item2'},
{name: 'item3'},
{name: 'item4'},
{name: 'item5'}
]
},
methods: {
reorder: function (element, sibling) {
var children = element.parentNode.querySelectorAll(".block");
var length = this.list.length;
var ids = [];
for (var i = 0; i < length; i++) {
if (children[i].id) {
ids.push(children[i].id);
}
children[i].id = i;
}
var vm = this;
var newArr = ids.map(function (id) {
return vm.list[id];
});
this.list = newArr;
}
}
});
组件如下:
Vue.component('block', {
template: '#block-template',
props: ['index', 'name', 'item'],
methods: {
removeItem: function (item) {
vm.list.$remove(item);
}
}
});
我这样称呼德拉古拉:
dragula([document.getElementById('draggable')]).on('drop', function (el, target, source, sibling) {
vm.reorder(el, sibling);
});
这个 fiddle 工作正常但不使用组件:https://jsfiddle.net/z2s83yfL/1/
我有两个问题。首先,我绑定了数组索引并将其用作 id。索引正在更改,这也导致 id 更改。其次,在模板标签上使用 v-for 会导致一些问题。我将标签更改为 div,现在可以使用了。
工作fiddle:https://jsfiddle.net/wfjawvnL/18/
Vue 内容:
Vue.component('block', {
template: '#block-template',
props: ['name', 'item'],
methods: {
removeItem: function (item) {
vm.list.$remove(item);
}
}
});
var vm = new Vue({
el: '#app',
data: {
list: [
{name: 'item1'},
{name: 'item2'},
{name: 'item3'},
{name: 'item4'},
{name: 'item5'}
]
},
ready: function() {
var self = this;
var from = null;
var drake = dragula([document.querySelector('#draggable')]);
drake.on('drag', function(element, source) {
var index = [].indexOf.call(element.parentNode.children, element);
from = index;
});
drake.on('drop', function(element, target, source, sibling) {
var index = [].indexOf.call(element.parentNode.children, element);
self.list.splice(index, 0, self.list.splice(from, 1)[0]);
});
}
});
HTML 东西:
<body>
<div id="app">
<div id="draggable" class="wrapper">
<div class="wrapper" v-for="item in list">
<block :item="item" :name="item.name">
</block>
</div>
</div>
<pre>{{ $data | json }}</pre>
</div>
</body>
<template id="block-template">
<div :class="[name, 'block']">
<div class="text name" v-on:click="removeItem(item)">{{ name }}</div>
<span class="delete" v-on:click="removeItem(item)">✗</span>
</div>
</template>