vue 實(shí)現(xiàn)可拖曳的樹狀結(jié)構(gòu)圖
最近用vue做了一個(gè)小項(xiàng)目--可拖曳的樹狀結(jié)構(gòu)圖。
Vue遞歸組件
結(jié)構(gòu)通過Vue的遞歸組件實(shí)現(xiàn)
布局使用flex,結(jié)構(gòu)線由CSS偽類實(shí)現(xiàn)
需要注意的是居中布局,當(dāng)X軸元素過多導(dǎo)致子元素寬度超出視圖,元素居中后雖然有滾動(dòng)條,但只能到達(dá)右邊的內(nèi)容,左邊的內(nèi)容會(huì)無法訪問,可以把父元素設(shè)置為inline-flex,寬度設(shè)置為auto。當(dāng)然,如果是上述的結(jié)構(gòu)則不會(huì)有這個(gè)問題,但遇到大數(shù)據(jù)渲染,還是困擾我了一下午。
drag事件
首先在需要在拖動(dòng)的元素上綁定draggable屬性,除了<a>和<img>標(biāo)簽設(shè)默認(rèn)為true,其他元素都需要設(shè)置下
然后是三個(gè)事件dragend
、dragover
、drop
(用Vue寫的,就不在事件前加on了)
注意dragover
需要去除默認(rèn)行為,在事件中給上$event.preventDefault()
,否則拖曳時(shí)鼠標(biāo)會(huì)有🚫標(biāo)志,使拖動(dòng)無效。
drag的元素把值傳到drop的位置,需要使用$event.dataTransfer.setData("node", transNodeData)
"node"
是相當(dāng)于傳遞數(shù)據(jù)的變量名,需要先JSON.stringify()
methods:{ dragstart(e,nodeObj){ console.log('🐉drag移動(dòng)的點(diǎn)位',nodeObj.name,); let transData=JSON.stringify(nodeObj)//拖曳傳遞過去的數(shù)據(jù)先轉(zhuǎn)為JSON格式 e.dataTransfer.setData("node",transData) }, dragover(e){ e.preventDefault() }, drop(e,nodeObj){ console.log('🐉drop到的點(diǎn)位',nodeObj.name); let getData=JSON.parse( e.dataTransfer.getData("node")) console.log('獲取了數(shù)據(jù)',getData); } }
了解了這一點(diǎn),接下來要做的就是把獲取的拖曳點(diǎn)位數(shù)據(jù)放到放置點(diǎn)位的children
數(shù)組中,并在dragend
事件中把拖曳點(diǎn)位在父節(jié)點(diǎn)children
數(shù)組中刪除,節(jié)點(diǎn)的索引在dragstart
事件觸發(fā)時(shí)就獲取,并通過eventBus
這一組件通信方式傳遞給dragend
(也可以使用Vuex
)。
創(chuàng)建bus文件夾,新建index.js文件
import Vue from "vue" const busEvent= new Vue({ data(){ return{ dragNodeIndex:-1,//拖曳節(jié)點(diǎn)在父節(jié)點(diǎn)children數(shù)組中的index } }, created(){ this.$on("transDragNodeIndex", res=>{//通過$on來監(jiān)聽$emit,需要確保自定義事件在觸發(fā)前被監(jiān)聽,也就是訂閱先于發(fā)布,否則無法監(jiān)聽到數(shù)據(jù),我eventBus沒怎么用過,這算是個(gè)坑 this.dragNodeIndex=res }) } }) export default busEvent
在組件中引入eventBus
,此時(shí)在dragstart
中通過$emit
觸發(fā)自定義事件后,$on
就可以接收到這個(gè)數(shù)據(jù),在dragend
中,可以通過eventBus
獲取這一索引,然后在數(shù)組中刪除
接下來就是做一些邏輯判斷,例如父節(jié)點(diǎn)不能拖曳到子節(jié)點(diǎn),先通過遞歸方式把父節(jié)點(diǎn)上所有子節(jié)點(diǎn)的name遍歷進(jìn)一個(gè)數(shù)組,如果drop位置的name
在數(shù)組中就表明父到子了,設(shè)置狀態(tài)為true,
ifFatherDragToSon(dragObj,dropObj){//判斷是否父節(jié)點(diǎn)移動(dòng)到了子節(jié)點(diǎn) if (dragObj.children.length === 0) return false; let newArr = []; function getAllName(dragObj) { newArr.push(...dragObj.children); if (dragObj.children.length === 0) { return; } else { for (let i = 0; i < dragObj.children.length; i++) { getAllName(dragObj.children[i]); } } } getAllName(dragObj); if (newArr.includes(dropObj)) { return true; } return false; }
通過eventBus
讓dragend
事件獲取狀態(tài),為true
直接return
拖曳到自身也不行,直接return。特意在拎壺沖點(diǎn)位下加了個(gè)子節(jié)點(diǎn),主要就是為了驗(yàn)證通過節(jié)點(diǎn)在棧中的地址來判斷,而不是依據(jù)name
屬性
再一個(gè)就是提一下drag事件中的$event.dataTransfer.dropEffect
,可以獲取的值為move
、copy
、none
、link
,下圖中當(dāng)dropEffect
為🚫時(shí)拖曳點(diǎn)位消失了,其實(shí)就是執(zhí)行了dragend
事件中的代碼,而drop
事件中的代碼未執(zhí)行,所以這一步需要先做流程控制。另外說明,不同瀏覽器的默認(rèn)dropEffect
也是不同的,比如360瀏覽器。
以上就是vue 實(shí)現(xiàn)可拖曳的樹狀結(jié)構(gòu)圖的詳細(xì)內(nèi)容,更多關(guān)于vue 實(shí)現(xiàn)樹狀結(jié)構(gòu)圖的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
基于vue2.0動(dòng)態(tài)組件及render詳解
下面小編就為大家分享一篇基于vue2.0動(dòng)態(tài)組件及render詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-03-03vue大型項(xiàng)目之分模塊運(yùn)行/打包的實(shí)現(xiàn)
這篇文章主要介紹了vue大型項(xiàng)目之分模塊運(yùn)行/打包的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09關(guān)閉eslint檢查和ts檢查的簡(jiǎn)單步驟記錄
這篇文章主要給大家介紹了關(guān)于關(guān)閉eslint檢查和ts檢查的相關(guān)資料,eslint是一個(gè)JavaScript的校驗(yàn)插件,通常用來校驗(yàn)語法或代碼的書寫風(fēng)格,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-02-02Vuex中g(shù)etters和actions的使用補(bǔ)充說明
這篇文章主要介紹了在Vuex中關(guān)于getters和actions使用的補(bǔ)充作了簡(jiǎn)要說明,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2021-09-09從零搭建一個(gè)vite+vue3+ts規(guī)范基礎(chǔ)項(xiàng)目(搭建過程問題小結(jié))
這篇文章主要介紹了從零搭建一個(gè)vite+vue3+ts規(guī)范基礎(chǔ)項(xiàng)目,本項(xiàng)目已vite開始,所以按照vite官方的命令開始,對(duì)vite+vue3+ts項(xiàng)目搭建過程感興趣的朋友一起看看吧2022-05-05vue完成項(xiàng)目后,打包成靜態(tài)文件的方法
今天小編就為大家分享一篇vue完成項(xiàng)目后,打包成靜態(tài)文件的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-09-09vue單頁應(yīng)用在頁面刷新時(shí)保留狀態(tài)數(shù)據(jù)的方法
今天小編就為大家分享一篇vue單頁應(yīng)用在頁面刷新時(shí)保留狀態(tài)數(shù)據(jù)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-09-09vue使用js-audio-recorder實(shí)現(xiàn)錄音功能
這篇文章主要為大家詳細(xì)介紹了vue如何使用js-audio-recorder實(shí)現(xiàn)錄音功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-12-12