天天看点

Vue中操作真实DOM导致VDom和真实DOM不一致之Vue中使用Sortable

参考:

Vue中使用Sortable

场景:

使用sortable进行拖拽后,视图发生了改变,但是Vue中负责渲染视图的数据和视图不一致,更新渲染数据后会导致重新渲染,VDOM和真实dom不一致又会导致,渲染后把拖拽的视图结果复原。

解决方案:

sortable只负责采集信息,采集信息结束后恢复由于采集信息导致的视图变化,确保视图始终由Vue控制渲染

const targetContainer = document.getElementsByClassName('ant-spin-container')
const _this = this
/* eslint-disable no-new */
const itemContainer = targetContainer[0]
new Sortable(itemContainer, {
  animation: 150, // 排序动画的时间
  forceFallback: false, // 使用h5原生拖放
  // 排序发生变化后执行
  onUpdate: event => {
	const newIndex = event.newIndex
	const oldIndex = event.oldIndex
	const newItem = itemContainer.children[newIndex]
	const oldItem = itemContainer.children[oldIndex]
	// 修改数据顺序
	const tempData = _this.data.map(item => ({ id: item.id }))
	const newData = exchangeIndex(tempData, newIndex, oldIndex)
	// 更新到后端
	orderGroup(newData).then(result => {
	  // 解决vdom和真实dom不一致导致的拖拽回跳
	  // sortable只负责采集信息,采集信息结束后恢复由于采集信息导致的视图变化,确保视图始终由Vue控制渲染
	  itemContainer.removeChild(newItem)
	  if (newIndex > oldIndex) {
		itemContainer.insertBefore(newItem, oldItem)
	  } else {
		itemContainer.insertBefore(newItem, oldItem.nextSibling)
	  }

	  const sortResult = sortByOrder(result.data)
	  this.data = sortResult // 更新缓存顺序
	  this.dataSource = sortResult // 更新渲染顺序
	}).catch(err => {
	  console.log(err)
	})
  },
})