vue 實現(xiàn)可拖曳的樹狀結(jié)構(gòu)圖
最近用vue做了一個小項目--可拖曳的樹狀結(jié)構(gòu)圖。
Vue遞歸組件結(jié)構(gòu)通過Vue的遞歸組件實現(xiàn)
布局使用flex,結(jié)構(gòu)線由CSS偽類實現(xiàn)
需要注意的是居中布局,當(dāng)X軸元素過多導(dǎo)致子元素寬度超出視圖,元素居中后雖然有滾動條,但只能到達(dá)右邊的內(nèi)容,左邊的內(nèi)容會無法訪問,可以把父元素設(shè)置為inline-flex,寬度設(shè)置為auto。當(dāng)然,如果是上述的結(jié)構(gòu)則不會有這個問題,但遇到大數(shù)據(jù)渲染,還是困擾我了一下午。
drag事件首先在需要在拖動的元素上綁定draggable屬性,除了<a>和<img>標(biāo)簽設(shè)默認(rèn)為true,其他元素都需要設(shè)置下
然后是三個事件dragend、dragover、drop(用Vue寫的,就不在事件前加on了)
注意dragover需要去除默認(rèn)行為,在事件中給上$event.preventDefault(),否則拖曳時鼠標(biāo)會有🚫標(biāo)志,使拖動無效。
drag的元素把值傳到drop的位置,需要使用$event.dataTransfer.setData('node', transNodeData)
'node'是相當(dāng)于傳遞數(shù)據(jù)的變量名,需要先JSON.stringify()
methods:{ dragstart(e,nodeObj){ console.log(’🐉drag移動的點位’,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到的點位’,nodeObj.name); let getData=JSON.parse( e.dataTransfer.getData('node')) console.log(’獲取了數(shù)據(jù)’,getData); } }
了解了這一點,接下來要做的就是把獲取的拖曳點位數(shù)據(jù)放到放置點位的children數(shù)組中,并在dragend事件中把拖曳點位在父節(jié)點children數(shù)組中刪除,節(jié)點的索引在dragstart事件觸發(fā)時就獲取,并通過eventBus這一組件通信方式傳遞給dragend(也可以使用Vuex)。
創(chuàng)建bus文件夾,新建index.js文件
import Vue from 'vue'const busEvent= new Vue({ data(){ return{ dragNodeIndex:-1,//拖曳節(jié)點在父節(jié)點children數(shù)組中的index } }, created(){ this.$on('transDragNodeIndex', res=>{//通過$on來監(jiān)聽$emit,需要確保自定義事件在觸發(fā)前被監(jiān)聽,也就是訂閱先于發(fā)布,否則無法監(jiān)聽到數(shù)據(jù),我eventBus沒怎么用過,這算是個坑 this.dragNodeIndex=res }) }})export default busEvent
在組件中引入eventBus,此時在dragstart中通過$emit觸發(fā)自定義事件后,$on就可以接收到這個數(shù)據(jù),在dragend中,可以通過eventBus獲取這一索引,然后在數(shù)組中刪除
接下來就是做一些邏輯判斷,例如父節(jié)點不能拖曳到子節(jié)點,先通過遞歸方式把父節(jié)點上所有子節(jié)點的name遍歷進(jìn)一個數(shù)組,如果drop位置的name在數(shù)組中就表明父到子了,設(shè)置狀態(tài)為true,
ifFatherDragToSon(dragObj,dropObj){//判斷是否父節(jié)點移動到了子節(jié)點 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。特意在拎壺沖點位下加了個子節(jié)點,主要就是為了驗證通過節(jié)點在棧中的地址來判斷,而不是依據(jù)name屬性
再一個就是提一下drag事件中的$event.dataTransfer.dropEffect,可以獲取的值為move、copy、none、link,下圖中當(dāng)dropEffect為🚫時拖曳點位消失了,其實就是執(zhí)行了dragend事件中的代碼,而drop事件中的代碼未執(zhí)行,所以這一步需要先做流程控制。另外說明,不同瀏覽器的默認(rèn)dropEffect也是不同的,比如360瀏覽器。
代碼連接
以上就是vue 實現(xiàn)可拖曳的樹狀結(jié)構(gòu)圖的詳細(xì)內(nèi)容,更多關(guān)于vue 實現(xiàn)樹狀結(jié)構(gòu)圖的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!
相關(guān)文章:
1. IntelliJ IDEA導(dǎo)入jar包的方法2. Python requests庫參數(shù)提交的注意事項總結(jié)3. 詳談ajax返回數(shù)據(jù)成功 卻進(jìn)入error的方法4. python ansible自動化運維工具執(zhí)行流程5. vue-electron中修改表格內(nèi)容并修改樣式6. JavaScript中l(wèi)ayim之整合右鍵菜單的示例代碼7. python操作mysql、excel、pdf的示例8. 匹配模式 - XSL教程 - 49. 通過Python pyecharts輸出保存圖片代碼實例10. javascript實現(xiàn)雪花飄落效果
