日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

html 树形图可拖拽,HTML5拖拽API实现vue树形拖拽组件

發布時間:2023/12/10 HTML 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 html 树形图可拖拽,HTML5拖拽API实现vue树形拖拽组件 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

因業務場景需要一個可拖拽修改節點位置的樹形組件,因此動手擼了一個,乘此機會摸了一把html5原生拖拽。近期有時間將核心部分代碼抽出,簡單說下實現方式。

1.樹形結構-組件遞歸使用

樹形結構非常簡單,tree組件作為父組件,結構如下

tree.vue

復制代碼

vue組件允許在它們自己的模板中調用自身,因此可以形成樹形結構,在組件中必須填寫唯一的name。

tree-node.vue

復制代碼

2.HTML5拖拽api

1.draggable屬性規定元素是否可拖動,目前Internet Explorer 9+, Firefox, Opera, Chrome, and Safari 支持 draggable 屬性

2.HTML 5 拖放api

ondragstart: 元素開始被拖動時觸發 作用在拖拽元素上

ondragenter:當拖曳元素進入目標元素的時候觸發的事件,作用在目標元素上

ondragover:拖拽元素在目標元素上移動的時候觸發的事件,作用在目標元素上

ondragleave:拖拽元素拖離開了目標元素時觸發,作用在目標元素上

ondrop:被拖拽的元素在目標元素上同時鼠標放開觸發的事件,作用在目標元素上

ondragend:當拖拽完成后觸發的事件,作用在被拖曳元素上

3.拖拽節點

定義變量

處理拖拽節點需要幾個關鍵變量

當前拖拽的節點

拖拽時經過的節點

最終放置的節點

因此定義了一個用于保存拖拽信息的對象

dragOverStatus: {

overNodeKey: "",

dropPosition: "",

dragNode: {}

}

復制代碼

綁定拖拽事件

這里將ondragstart事件綁定在子元素上,將其他事件綁定在父元素上,因為在測試真機IE10的時候,發現ondragstart和其他事件綁定在同一個元素上,無法觸發ondragenter等事件。

復制代碼mounted() {

//綁定拖拽事件

if (this.root.draggable) {

this.$refs.draggAbleDom.draggable = !this.nodeData.noDrag;

this.$refs.draggAbleDom.ondragstart = this.onDragStart;

this.$refs.dropTarget.ondragenter = this.onDragEnter;

this.$refs.dropTarget.ondragover = this.onDragOver;

this.$refs.dropTarget.ondragleave = this.onDragLeave;

this.$refs.dropTarget.ondrop = this.onDrop;

this.$refs.dropTarget.ondragend = this.onDragEnd;

}

}

復制代碼

觸發某節點的拖拽事件時,就可以從拖拽事件里拿到當前節點實例。

使用HTML5提供的專門的拖拽與拖放API,原生的實現了復雜的操作,不需要自己用鼠標事件模擬,因此實現拖拽效果非常簡單。

(1).開始拖拽:在拖拽元素上觸發,事件內只需要保存當前拖拽節點的信息即可

onDragStart(e, treeNode) {

this.dragOverStatus.dragNode = {

nodeData: treeNode.nodeData,

parentNode: treeNode.parentNodeData

};

this.$emit("on-dragStart", {

treeNode: treeNode.nodeData,

parentNode: treeNode.parentNodeData,

event: e

});

}

復制代碼

(2).進入目標節點:在目標元素上觸發,主要保存當前經過的節點的key,然后向外層發出事件,供組件調用者做其他操作。為了避免拖拽一個元素快速經過許多個節點時頻繁發出事件,設置定時器當停留一定時間后觸發。

onDragEnter(e, treeNode) {

//當沒有設置拖拽節點時,禁止作為目標節點

if (!this.hasDragNode()) {

return;

}

this.dragOverStatus.overNodeKey = "";

//拖拽節點與目標節點是同一個,return掉

if (

treeNode.nodeData._hash === this.dragOverStatus.dragNode.nodeData._hash

) {

return;

}

this.dragOverStatus.overNodeKey = treeNode.nodeData._hash; //當前經過的可放置的節點的key

//當前節點禁止做為放置節點時

if (treeNode.nodeData.noDrop) {

return;

}

//設置dragEnter定時器,停留250毫秒后觸發事件

if (!this.delayedDragEnterLogic) {

this.delayedDragEnterLogic = {};

}

Object.keys(this.delayedDragEnterLogic).forEach(key => {

clearTimeout(this.delayedDragEnterLogic[key]);

});

this.delayedDragEnterLogic[

treeNode.nodeData._hash

] = setTimeout(() => {

if (!treeNode.nodeData.isExpand) {

treeNode.toggleCollapseStatus();

}

this.$emit("on-dragEnter", {

treeNode: treeNode.nodeData,

parentNode: treeNode.parentNodeData,

event: e

});

}, 250);

}

復制代碼

(3).在目標節點上經過:在目標元素上觸發,即時計算鼠標在目標節點上的位置,用于判斷最終的放置位置,0(作為目標節點的子節點),-1(放置在目標節點的前面),1(放置在目標節點的后面),顯示相應的樣式。

onDragOver(e, treeNode) {

//當沒有設置拖拽節點時,禁止作為目標節點

if (!this.hasDragNode()) {

return;

}

if (

this.dragOverStatus.overNodeKey === treeNode.nodeData._hash

) {

this.dragOverStatus.dropPosition = this.calDropPosition(e); //放置標識0,-1,1

}

this.$emit("on-dragOver", {

treeNode: treeNode.nodeData,

parentNode: treeNode.parentNodeData,

event: e

});

this.dragOverClass = this.setDragOverClass();//設置鼠標經過樣式

},

復制代碼

當鼠標處于目標節點內目標節點偏上方(1/5處),則意為放在目標節點前面-同級,當鼠標處于目標節點內目標節點偏下方(1/5處),意為放在目標節點后面-同級,否則作為目標節點的子節點

calDropPosition(e) {

var offsetTop = this.getOffset(e.target).top;

var offsetHeight = e.target.offsetHeight;

var pageY = e.pageY;

var gapHeight = 0.2 * offsetHeight;

if (pageY > offsetTop + offsetHeight - gapHeight) {

//放在目標節點后面-同級

return 1;

}

if (pageY < offsetTop + gapHeight) {

//放在目標節點前面-同級

return -1;

}

//放在目標節點里面-作為子節點

return 0;

}

復制代碼

(4).放置節點:在目標元素上觸發,此時將拖拽的信息變量作為參數將事件發射到外層,其余操作由外層來決定即可。

onDrop(e, treeNode) {

//當沒有設置拖拽節點時,禁止作為目標節點

if (!this.hasDragNode()) {

return;

}

//當前節點禁止拖拽時

if (treeNode.nodeData.noDrop) {

return;

}

//拖拽節點與目標節點是同一個,不做任何操作

if (

this.dragOverStatus.dragNode.nodeData._hash === treeNode.nodeData._hash

) {

return;

}

var res = {

event: e,

dragNode: this.dragOverStatus.dragNode,

dropNode: {

nodeData: treeNode.nodeData,

parentNode: treeNode.parentNodeData

},

dropPosition: this.dragOverStatus.dropPosition

};

this.$emit("on-drop", res);

}

復制代碼

(5).拖拽結束:作用在拖拽元素上,拖拽結束后將清除變量,恢復樣式。

onDragEnd(e, treeNode) {

//當沒有設置拖拽節點時,禁止作為目標節點

if (!this.hasDragNode()) {

return;

}

//當前節點禁止拖拽時

if (treeNode.nodeData.noDrop) {

return true;

}

this.dragOverStatus.dragNode = null;

this.dragOverStatus.overNodeKey = "";

this.$emit("on-dragEnd", {

treeNode: treeNode.nodeData,

parentNode: treeNode.parentNodeData,

event: e

});

}

復制代碼

4.應用

調用樹形拖拽組件,獲取拖拽過程中的拖拽節點,目標節點,以及放置位置,具體處理拖拽結果由調用方決定,可以是通過調接口更新樹結構,也可以由前端處理輸入數據,更新視圖。

復制代碼getDropData(info) {

var dragData = info.dragNode.nodeData;

var dragParent = info.dragNode.parentNode;

var dropData = info.dropNode.nodeData;

var dropParent = info.dropNode.parentNode;

var dropPosition = info.dropPosition; //0作為子級,-1放在目標節點前面,1放在目標節點后面

//把拖拽元素從父節點中刪除

dragParent.children.splice(dragParent.children.indexOf(dragData), 1);

if (dropPosition === 0) {

dropData.children.push(dragData);

} else {

var index = dropParent.children.indexOf(dropData);

if (dropPosition === -1) {

dropParent.children.splice(index, 0, dragData);

} else {

dropParent.children.splice(index + 1, 0, dragData);

}

}

}

復制代碼

作為子節點,改變層級

修改排序,將拖拽節點放在目標節點后面

修改排序,將拖拽節點放在目標節點前面

總結

以上是生活随笔為你收集整理的html 树形图可拖拽,HTML5拖拽API实现vue树形拖拽组件的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。