这篇文章将为大家详细讲解有关Sortable怎么在Vue中使用,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
假设我们的列表元素数组是
[‘A','B','C','D']
渲染出来后的DOM节点是
[$A,$B,$C,$D]
那么Virtual Dom对应的结构就是
[{elm:$A,data:'A'},
{elm:$B,data:'B'},
{elm:$C,data:'C'},
{elm:$D,data:'D'}]
假设拖拽排序之后,真实的DOM变为
[$B,$A,$C,$D]
此时我们只操作了真实DOM,改编了它的位置,而Virtual Dom的结构并没有改变,依然是
[{elm:$A,data:'A'},
{elm:$B,data:'B'},
{elm:$C,data:'C'},
{elm:$D,data:'D'}]
此时我们把列表元素也按照真实DOM排序后变成
[‘B','A','C','D']
这时候根据Diff算法,计算出的Patch为,VNode前两项是同类型的节点,所以直接更新,即把$A节点更新成$B,把$B节点更新成$A,真实DOM又变回了
[$A,$B,$C,$D]
所以就出现了拖拽之后又被Patch算法更新了一次的问题,操作路径可以简单理解为
拖拽移动真实DOM -> 操作数据数组 -> Patch算法再更新真实DOM
根本原因
根本原因是Virtual DOM和真实DOM之间出现了不一致。
所以在Vue2.0以前,因为没有引入Virtual DOM,这个问题是不存在的。
在使用Vue框架的时候要尽量避免直接操作DOM
解决方案
1、通过设置key唯一标志每一个VNode,这也是Vue推荐的使用v-for指令的方式。因为在判断两个VNode是否为同类型时会调用sameVnode方法,优先判断key是否相同
function sameVnode (a, b) {
return (
a.key === b.key &&
a.tag === b.tag &&
a.isComment === b.isComment &&
isDef(a.data) === isDef(b.data) &&
sameInputType(a, b)
)
}
2、因为根本原因是真实DOM和VNode不一致,所以可以通过把拖拽移动真实DOM的操作还原,即在回调函数里,把[$B,$A,$C,$D]还原成[$A,$B,$C,$D],让DOM的操作交还给Vue
拖拽移动真实DOM ->还原移动操作 -> 操作数据数组 -> Patch算法再更新真实DOM
代码如下
var app = new Vue({
el: '#app',
mounted:function(){
var $ul = this.$el.querySelector('#ul')
var that = this
new Sortable($ul, {
onUpdate:function(event){
var newIndex = event.newIndex,
oldIndex = event.oldIndex
$li = $ul.children[newIndex],
$oldLi = $ul.children[oldIndex]
// 先删除移动的节点
$ul.removeChild($li)
// 再插入移动的节点到原有节点,还原了移动的操作
if(newIndex > oldIndex) {
$ul.insertBefore($li,$oldLi)
} else {
$ul.insertBefore($li,$oldLi.nextSibling)
}
// 更新items数组
var item = that.items.splice(oldIndex,1)
that.items.splice(newIndex,0,item[0])
// 下一个tick就会走patch更新
}
})
},
data:function() {
return {
message: 'Hello Vue!',
items:[{
key:'1',
name:'1'
},{
key:'2',
name:'2'
},{
key:'3',
name:'3'
},{
key:'4',
name:'4'
}]
}
},
watch:{
items:function(){
console.log(this.items.map(item => item.name))
}
}
})
3.暴力解决!不走patch更新,通过v-if设置,直接重新渲染一遍。当然不建议这么做,只是提供这种思路~
mounted:function(){
var $ul = this.$el.querySelector('#ul')
var that = this
var updateFunc = function(event){
var newIndex = event.newIndex,
oldIndex = event.oldIndex
var item = that.items.splice(oldIndex,1)
that.items.splice(newIndex,0,item[0])
// 暴力重新渲染!
that.reRender = false
// 借助nextTick和v-if重新渲染
that.$nextTick(function(){
that.reRender = true
that.$nextTick(function(){
// 重新渲染之后,重新进行Sortable绑定
new Sortable(that.$el.querySelector('#ul'), {
onUpdate:updateFunc
})
})
})
}
new Sortable($ul, {
onUpdate:updateFunc
})
},
关于Sortable怎么在Vue中使用就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。