vue 實現可拖曳的樹狀結構圖

最近用vue做瞭一個小項目–可拖曳的樹狀結構圖。

Vue遞歸組件

結構通過Vue的遞歸組件實現

佈局使用flex,結構線由CSS偽類實現

需要註意的是居中佈局,當X軸元素過多導致子元素寬度超出視圖,元素居中後雖然有滾動條,但隻能到達右邊的內容,左邊的內容會無法訪問,可以把父元素設置為inline-flex,寬度設置為auto。當然,如果是上述的結構則不會有這個問題,但遇到大數據渲染,還是困擾我瞭一下午。

drag事件

首先在需要在拖動的元素上綁定draggable屬性,除瞭<a>和<img>標簽設默認為true,其他元素都需要設置下

然後是三個事件dragenddragoverdrop(用Vue寫的,就不在事件前加on瞭)

註意dragover需要去除默認行為,在事件中給上$event.preventDefault(),否則拖曳時鼠標會有🚫標志,使拖動無效。

drag的元素把值傳到drop的位置,需要使用$event.dataTransfer.setData("node", transNodeData)

"node"是相當於傳遞數據的變量名,需要先JSON.stringify()

methods:{
    dragstart(e,nodeObj){
      console.log('🐉drag移動的點位',nodeObj.name,);
      let transData=JSON.stringify(nodeObj)//拖曳傳遞過去的數據先轉為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('獲取瞭數據',getData);
    }
  }

瞭解瞭這一點,接下來要做的就是把獲取的拖曳點位數據放到放置點位的children數組中,並在dragend事件中把拖曳點位在父節點children數組中刪除,節點的索引在dragstart事件觸發時就獲取,並通過eventBus這一組件通信方式傳遞給dragend(也可以使用Vuex)。

創建bus文件夾,新建index.js文件

import Vue from "vue"
const busEvent= new Vue({
  data(){
    return{
      dragNodeIndex:-1,//拖曳節點在父節點children數組中的index
    }
  },
  created(){
    this.$on("transDragNodeIndex", res=>{//通過$on來監聽$emit,需要確保自定義事件在觸發前被監聽,也就是訂閱先於發佈,否則無法監聽到數據,我eventBus沒怎麼用過,這算是個坑
      this.dragNodeIndex=res
    })
  }
})

export default busEvent

在組件中引入eventBus,此時在dragstart中通過$emit觸發自定義事件後,$on就可以接收到這個數據,在dragend中,可以通過eventBus獲取這一索引,然後在數組中刪除

接下來就是做一些邏輯判斷,例如父節點不能拖曳到子節點,先通過遞歸方式把父節點上所有子節點的name遍歷進一個數組,如果drop位置的name在數組中就表明父到子瞭,設置狀態為true,

ifFatherDragToSon(dragObj,dropObj){//判斷是否父節點移動到瞭子節點
      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;
    }

通過eventBusdragend事件獲取狀態,為true直接return

拖曳到自身也不行,直接return。特意在拎壺沖點位下加瞭個子節點,主要就是為瞭驗證通過節點在棧中的地址來判斷,而不是依據name屬性

再一個就是提一下drag事件中的$event.dataTransfer.dropEffect,可以獲取的值為movecopynonelink,下圖中當dropEffect為🚫時拖曳點位消失瞭,其實就是執行瞭dragend事件中的代碼,而drop事件中的代碼未執行,所以這一步需要先做流程控制。另外說明,不同瀏覽器的默認dropEffect也是不同的,比如360瀏覽器。

代碼連接

以上就是vue 實現可拖曳的樹狀結構圖的詳細內容,更多關於vue 實現樹狀結構圖的資料請關註WalkonNet其它相關文章!

推薦閱讀:

    None Found