【Web前端问题】Vue操作Dom后,数据和视图展示的不一样(拖拽排序)(iview树组件)
项目里有个需求是树组件要进行节点的拖拽排序
拖拽完成后,数据排序正确,但是视图层并不是按照数据顺序渲染(不是双向绑定吗)
点击树组件的收起展开后,显示正常,看了源组件,用了v-if指令,重新写了dom
源组件里面watch触发了两次,在mouseup事件(做了数据排序)
如果同一个 watcher 被多次触发,只会被推入到队列中一次。
不知是不是这个原因,是的话怎么解决
<template> <div>
<Tree :data="getTreeData" :render="sel" ref="tree"></Tree>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: "tree",
data(){
return {
saveVal:'',
originNode:'',
}
},
props:['name'],
computed:{
...mapGetters([
'getTreeData'
])
},
watch:{
},
methods:{
sel(h,{root,node,data}){
if(this.name === 'set'){
return this.renderContentSet(h,{root,node,data})
}else if(this.name === 'relation'){
return this.renderContentPack(h,{root,node,data})
}else{
return this.renderContentDel(h,{root,node,data})
}
},
renderContentSet(h,{root,node,data}){ //书本编辑树
return h('div',{
class:['hover','clear'],
style:{display:'inline-block',userSelect:'none'}
},[
h('span',{
style:{fontSize:'16px',cursor:'pointer',float:'left'},
on:{
mousedown:(e)=>{
if($(e.target).attr('contentEditable')){return;}
if( e.which !== 1 ){return;}
let sY = e.clientY,sTop,targetNode,cloneNode,hasClone = 1;
const parentKey = root.find(el => el === node).parent !== 'undefined' ? root.find(el => el === node).parent : '';
if(parentKey === 0 || parentKey){
const parent = root.find(el => el.nodeKey === parentKey).node;
const index = parent.children.indexOf(data);
targetNode = $(e.target).parent().parent().parent();
cloneNode = targetNode.clone().empty().css({'height': targetNode.height() +'px',margin:'8px 0'});
sTop = targetNode.position().top;
let obj = {sY,targetNode,cloneNode,sTop,hasClone,index,parent};
this.dragNode(root,node,data,obj)
}else{
}
}
}
},data.title),
h('div',{ class:['iconShow'],style:{display:'none',marginLeft:'5px',cursor:'pointer',float:'left'} },[
h('Button',{
props:{type:'ghost',icon:'ios-plus-empty',size:'small'},
style:{marginRight:'5px'},
on:{
click:()=>{ this.addNode(data) }
}
}),
h('Button',{
props:{type:'ghost',icon:'ios-compose',size:'small'},
style:{marginRight:'5px'},
on:{
click:(e)=>{ this.changeTitle(e,data) }
}
}),
h('Button',{
props:{type:'ghost',icon:'ios-close-empty',size:'small'},
style:{marginRight:'5px'},
on:{
click:()=>{ this.deleteNode(root,node,data) }
}
})
]),
])
},
addNode(data){ //添加节点
const children = data.children || [];
data.expand = true;
children.push({title:'未定义标题',expand:true});
this.$set(data, 'children', children);
},
changeTitle(e,data){ // 改变标题
$(e.target).parents('.iconShow').siblings('span').attr('contentEditable','true').focus();
$(e.target).parents('.iconShow').siblings('span').blur(function(){
if(!$(this).html()){
$(this).html( data.title )
}else{
data.title = $(this).html()
}
$(this).removeAttr('contentEditable')
});
},
deleteNode(root, node, data) { // 删除节点
if(data.children && data.children.length > 0){
this.$Modal.error({
title: '提示',
content: '存在子目录,无法删除'
});
return;
}
const parentKey = root.find(el => el === node).parent !== 'undefined' ? root.find(el => el === node).parent : '';
if(parentKey === 0 || parentKey){
const parent = root.find(el => el.nodeKey === parentKey).node;
const index = parent.children.indexOf(data);
parent.children.splice(index, 1);
}else{
for(let i=0;i<this.getTreeData.length;i++){
if(data.id===this.getTreeData[i].id){
this.getTreeData.splice(i,1);
break;
}
}
}
},
dragNode(root,node,data,obj){ //拖拽节点
let This = this;
document.onmousemove = function(e){
let nY = e.clientY,top,prev,next,scrollTop = obj.targetNode.parents('.TabPane').scrollTop();
if(obj.hasClone){
obj.targetNode.before(obj.cloneNode).css({
'position':'absolute',
'width':'auto',
}).appendTo(obj.targetNode.parent());
obj.hasClone = 0;
}
top = obj.sTop + nY - obj.sY ;
obj.targetNode.css({
top: top + 'px'
});
prev = obj.cloneNode.prev().not('.hover');
next = obj.cloneNode.next().not( obj.targetNode );
//向上排序
if(prev.length && scrollTop + top < prev.position()['top'] + prev.outerHeight()/2){
obj.cloneNode.after(prev)
}
//向下排序
if(next.length && scrollTop + top > next.position()['top'] + next.outerHeight()/2 - 20){
obj.cloneNode.before(next)
}
};
document.onmouseup = function(e){
if( !obj.hasClone ){
let i = obj.cloneNode.index()-2;
obj.cloneNode.before(obj.targetNode.removeAttr('style')).remove();
This.findNode(This.getTreeData,obj.parent);
if(i - obj.index >= 0) {
This.originNode.children.splice(i+1,0,This.originNode.children[obj.index]);
This.originNode.children.splice(obj.index,1)
}else{
This.originNode.children.splice(i,0,This.originNode.children[obj.index]);
This.originNode.children.splice(obj.index + 1,1)
}
This.$set(obj.parent,'children',This.originNode.children)
// obj.parent.children.splice(0,obj.parent.children.length);
//
// This.originNode.children.forEach(function(item){
// obj.parent.children.push(item)
// });
// This.$set(This.getTreeData[0],'children',[])
// setTimeout(function(){
// This.$set(obj.parent,'children',This.originNode.children)
// },60)
}
document.onmousemove = null;
document.onmouseup = null;
}
},
findNode(root,node){ //递归查找节点
for(let item of root){
if(item.id !== node.id){
if(item.children){
this.originNode = JSON.parse(JSON.stringify(item.children))
this.findNode(this.originNode,node)
}
}else{
return this.originNode = JSON.parse(JSON.stringify(item))
}
}
},
renderContentPack(h,{root,node,data}){ //书本关联树
},
renderContentDel(h,{root,node,data}){ // 书本详情树
return h('div',{
class:['treeBox'],
style:{display:'inline-block',width:'100%'},
on:{click:()=>{}}
},[
data.ultima ? h('span',{
class:[this.publishStatus(data).class],
style:{marginRight:'5px',padding:'0 5px',color:'#fff',borderRadius:'2px'}
},this.publishStatus(data).text) : '',
h('span',{ class:['cite'] },data.title),
h('span', { class:['treeBadge'] } ,data.count)
])
},
publishStatus(data){ // 判断书本状态
let obj = {};
switch (data.publishStatus){
case 0:
case 1:
obj.class = 'pink';
obj.text = '录入中';
break;
case 2:
obj.class = 'yellow';
obj.text = '待校对';
break;
case 3:
obj.class = 'yellow';
obj.text = '校对中';
break;
case 4:
obj.class = 'green';
obj.text = '已校对';
break;
case 5:
obj.class = 'green';
obj.text = '已发布';
break;
default:
obj.text = '未知状态';
break
}
return obj
},
},
mounted(){
console.log(this.$refs.tree)
}
}
</script>
<style scoped>
</style>
回答:
可以使用官方推荐的nextTick 函数来执行拖曳后的回调 官方文档:https://cn.vuejs.org/v2/api/#...
以上是 【Web前端问题】Vue操作Dom后,数据和视图展示的不一样(拖拽排序)(iview树组件) 的全部内容, 来源链接: utcz.com/a/136040.html