組件之間的拖拽

項目中涉及到三種類型的拖拽:

1.el-tree拖拽字段至div,表格;

2.多個div之間的拖拽;

3.表格之間列的拖拽;

 

實現代碼:

1.el-tree拖拽字段至div,表格;

 1.el-tree設置字段可拖拽至外部:

<el-tree
  ref="tree"
  @node-drag-start="handleDragStart"
  @node-drag-enter="handleDragEnter"
  @node-drag-leave="handleDragLeave"
  @node-drag-over="handleDragOver"
  @node-drag-end="handleDragEnd"
  @node-drop="handleDrop"
  draggable
  :allow-drop="allowDrop"
  :allow-drag="allowDrag"
>

handleDragStart(node, ev) {
  let dt = ev.dataTransfer;
  ev.dataTransfer.effectAllowed = "copy";
  dt.setData("text/plain", JSON.stringify(node.data));
},
handleDragEnter(draggingNode, dropNode, ev) {},
handleDragLeave(draggingNode, dropNode, ev) {},
handleDragOver(draggingNode, dropNode, ev) {},
handleDragEnd(draggingNode, dropNode, dropType, ev) {},
handleDrop(draggingNode, dropNode, dropType, ev) {},
allowDrop(draggingNode, dropNode, type) {
  return false;
},
allowDrag(draggingNode) {
  return true;
},

2.div及表格設置可接收el-tree拖拽過來的字段信息:

@drop="(e) => handleTargetDrop(e, index)"
@dragover.prevent

// 字段列表拖拽字段至報表列
handleTargetDrop(e, index) {
  let data = e.dataTransfer;
  if (!this.isJsonString(data.getData("text/plain"))) return;
  let content = JSON.parse(data.getData("text/plain"));
  let newList = JSON.parse(JSON.stringify(this.listCheckedFields));
  newList.splice(index + 1, 0, content);
  this.dragRowColumnReportColumns(newList);
  e.preventDefault();
  // 通常不需要阻止冒泡,但是當出現容器嵌套時最好這麼做
  // 它可以防止節點被添加到數組中兩次
  e.stopPropagation();
},

// 判斷是否可以轉換爲json數據
isJsonString(str) {
  try {
    if (typeof JSON.parse(str) == "object") {
      return true;
    }
  } catch (e) {}
  return false;
},

若是用在表格中則drop方法需要添加到表頭標籤上,事件中可以獲取到拖拽過來的字段信息,若是想要拖拽到固定位置,可以在循環的表頭或div中傳入index來動態插入。

dragRowColumnReportColumns方法用來在獲取到拖拽之後的數據集合時,通過請求接口來渲染頁面數據。

2.多個div之間的拖拽;

 1.組行、組列、報表列這三個div之間可以互相拖拽;可以將這三個div進行分組;

<draggable
  v-model="form.choosedColumnFiledsData"
  @update="dragRowColumnReportColumns"
  @add="dragRowColumnReportColumns"
  v-bind="dragOptions"
>
</draggable>

computed: {
  dragOptions() {
    return {
      animation: 300,
      group: "description",
      ghostClass: "ghost",
      chosenClass: "chosen",
    };
  },
},

// 組行、組列、報表列拖拽
dragRowColumnReportColumns() {
  // 數組去重
  this.form.chooseReportColumnsData = this.unique(
    this.form.chooseReportColumnsData
  );
  let e = {
    chooseRowFiledsData: this.form.chooseRowFiledsData,
    choosedColumnFiledsData: this.form.choosedColumnFiledsData,
    chooseReportColumnsData: this.form.chooseReportColumnsData,
  };
  this.$bus.$emit("dragRowColumnReportColumnsBus", e);
},

 通過在dragOptions中設置相同的group,可以實現對應div之間的互相拖拽,各自內部也可以拖拽,然後通過v-model綁定拖拽之後的數據,在update和add方法中將拖拽後的數據請求接口,渲染頁面。

3.表格之間列的拖拽;

 表格的列之間可以互相拖拽;

1.給表格的父元素設置class,給el-table設置v-if:

<div class="draggable">
  <el-table
    :data="tableData"
    border
    :fit="true"
    :cell-style="cellClass"
    v-if="showTable"
  >

  </el-table>
</div>

因爲使用Sortable.create進行拖拽後,表格會直接修改爲拖拽之後的,儘管表格綁定的列數據並未改變,所以需要使用v-if來控制表格的重新渲染。

2.表格列進行拖拽時,獲取到拖拽之後的數據,請求接口:

// 表格列的拖拽
columnDrop() {
  const wrapperTr = document.querySelector(
    ".draggable .el-table__header-wrapper tr"
  );
  if (!wrapperTr) return;
  this.sortable = Sortable.create(wrapperTr, {
    animation: 180,
    delay: 0,
    dragClass: "chosen",
    onEnd: (evt) => {
      let newList = JSON.parse(JSON.stringify(this.listCheckedFields));
      const oldItem = newList[evt.oldIndex];
      newList.splice(evt.oldIndex, 1);
      newList.splice(evt.newIndex, 0, oldItem);
      // 拖拽之後會改變表格列順序,目前沒辦法控制,但數據並未改變,可以重新渲染表格來維持原數據
      this.showTable = false;
      this.$nextTick(() => {
        this.showTable = true;
      });
      this.dragRowColumnReportColumns(newList);
    },
  });
},

獲取到拖拽之後的數據之後,請求接口,渲染頁面。

 3.當表頭數據改變後,拖拽方法需要重新調用,不然拖拽會不生效:

watch: {
  listCheckedFields: {
    handler(newVal, oldVal) {
      this.$nextTick(() => {
        this.columnDrop();
      });
    },
    deep: true,
    immediate: true,
  },
},

 

注意:

1.三種拖拽中,第一種拖拽,即從el-tree中將字段拖拽至外部區域這種,僅能獲取到拖拽字段的信息,無法獲取到拖拽後的數據集合,所以需要根據drop綁定的事件再結合拖拽到目標位置的下標來組合拖拽後的數據;

2.後兩種拖拽,即多個div之間的拖拽、el-table之間的拖拽,這兩種均可以獲取到拖拽之後的數據,這樣就可以免去組裝數據,直接將拖拽後的數據作爲入參請求接口即可。

3.參考:

https://blog.csdn.net/qq_41694291/article/details/101384209

https://www.jianshu.com/p/34f44f2eb668

https://github.com/David-Desmaisons/draggable-example

https://blog.csdn.net/weixin_41192489/article/details/114086578

https://www.cnblogs.com/wisewrong/p/8820508.html

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章