項目里有個需求是樹組件要進行節(jié)點的拖拽排序
拖拽完成后,數(shù)據(jù)排序正確,但是視圖層并不是按照數(shù)據(jù)順序渲染(不是雙向綁定嗎)
點擊樹組件的收起展開后,顯示正常,看了源組件,用了v-if指令,重新寫了dom
源組件里面watch觸發(fā)了兩次,在mouseup事件(做了數(shù)據(jù)排序)
如果同一個 watcher 被多次觸發(fā),只會被推入到隊列中一次。
不知是不是這個原因,是的話怎么解決
<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){ //添加節(jié)點
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) { // 刪除節(jié)點
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){ //拖拽節(jié)點
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){ //遞歸查找節(jié)點
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}){ //書本關(guān)聯(lián)樹
},
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){ // 判斷書本狀態(tài)
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 = '已發(fā)布';
break;
default:
obj.text = '未知狀態(tài)';
break
}
return obj
},
},
mounted(){
console.log(this.$refs.tree)
}
}
</script>
<style scoped>
</style>
可以使用官方推薦的nextTick 函數(shù)來執(zhí)行拖曳后的回調(diào) 官方文檔:https://cn.vuejs.org/v2/api/#...
北大青鳥APTECH成立于1999年。依托北京大學優(yōu)質(zhì)雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國IT技能型緊缺人才,是大數(shù)據(jù)專業(yè)的國家
達內(nèi)教育集團成立于2002年,是一家由留學海歸創(chuàng)辦的高端職業(yè)教育培訓機構(gòu),是中國一站式人才培養(yǎng)平臺、一站式人才輸送平臺。2014年4月3日在美國成功上市,融資1
北大課工場是北京大學校辦產(chǎn)業(yè)為響應國家深化產(chǎn)教融合/校企合作的政策,積極推進“中國制造2025”,實現(xiàn)中華民族偉大復興的升級產(chǎn)業(yè)鏈。利用北京大學優(yōu)質(zhì)教育資源及背
博為峰,中國職業(yè)人才培訓領(lǐng)域的先行者
曾工作于聯(lián)想擔任系統(tǒng)開發(fā)工程師,曾在博彥科技股份有限公司擔任項目經(jīng)理從事移動互聯(lián)網(wǎng)管理及研發(fā)工作,曾創(chuàng)辦藍懿科技有限責任公司從事總經(jīng)理職務(wù)負責iOS教學及管理工作。
浪潮集團項目經(jīng)理。精通Java與.NET 技術(shù), 熟練的跨平臺面向?qū)ο箝_發(fā)經(jīng)驗,技術(shù)功底深厚。 授課風格 授課風格清新自然、條理清晰、主次分明、重點難點突出、引人入勝。
精通HTML5和CSS3;Javascript及主流js庫,具有快速界面開發(fā)的能力,對瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網(wǎng)頁制作和網(wǎng)頁游戲開發(fā)。
具有10 年的Java 企業(yè)應用開發(fā)經(jīng)驗。曾經(jīng)歷任德國Software AG 技術(shù)顧問,美國Dachieve 系統(tǒng)架構(gòu)師,美國AngelEngineers Inc. 系統(tǒng)架構(gòu)師。