树状组件的拖拽功能分析

树状的拖拽功能分析

1.Vue的树状已经组装好AP并支持拖拽,其中有node,data,type

组件部分

  <el-tree 
    :data="menus"
    :props="defaultProps"
    :expand-on-click-node="false"
    show-checkbox 
    node-key="catId"
    :default-expanded-keys="expandekey"
    :draggable="draggable"
    :allow-drop="allowDrop"
    @node-drop="handleDrop"
    ref="menuTree"
    >

data–对应绑定的数据,props–绑默认属性的API,expand-on-click-node是否只能点击箭头上进行展开节点(另一种解释),show-checkbox 是否为每项展示勾选,node-key为当项的唯一标识(数据区没有),default-expanded-keys表示树中默认展示的节点,draggable是否可拖拽,allow-drop为 拖拽时判定目标节点能否被放置(默认为三种: ‘prev’、‘inner’ 和 ‘next’ ),固定绑定的方法携带的参数(draggingNode, dropNode, type) ,node-drop为拖拽成功后触发事件,handleDrop也为以上三个

数据部分

data () {
    return {
      pCid: [],
      maxLevel: 0,
      draggable: true,
      updateNodes: [],
      dialogType: "",
      menus: [],
      expandekey: [],
      defaultProps: {
        children: "childrens",
        label: "name"
      }
    }
  }

方法部分

methods: {
    allowDrop(draggingNode, dropNode, type) {
      //1、被拖动的当前节点以及所在的父节点总层数不能大于3
      //1)、被拖动的当前节点总层数
      console.log("allowDrop:", draggingNode, dropNode, type);
      //
      this.countNodeLevel(draggingNode);
      //当前正在拖动的节点+父节点所在的深度不大于3即可
      let deep = Math.abs(this.maxLevel - draggingNode.level) + 1;
      console.log("深度:", deep);
      //   this.maxLevel
      if (type == "inner") {
        // console.log(
        //   `this.maxLevel:${this.maxLevel};draggingNode.data.catLevel:${draggingNode.data.catLevel};dropNode.level:${dropNode.level}`
        // );
        return deep + dropNode.level <= 3;
      } else {
        return deep + dropNode.parent.level <= 3;
      }
    },
    countNodeLevel(node) {
      //找到所有子节点,求出最大深度
      if (node.childNodes != null && node.childNodes.length > 0) {
        for (let i = 0; i < node.childNodes.length; i++) {
          if (node.childNodes[i].level > this.maxLevel) {
            this.maxLevel = node.childNodes[i].level;
          }
          this.countNodeLevel(node.childNodes[i]);
        }
      }
    },
    handleDrop(draggingNode, dropNode, dropType, ev) {
      console.log("handleDrop: ", draggingNode, dropNode, dropType);
      //1、当前节点最新的父节点id
      let pCid = 0;
      //2. 兄弟数组们
      let siblings = null;
      if (dropType == "before" || dropType == "after") {
        pCid = dropNode.parent.data.catId == 
               undefined? 0: dropNode.parent.data.catId;
        siblings = dropNode.parent.childNodes;//平级为父节点下的子节点数组
      } else {
        pCid = dropNode.data.catId;
        siblings = dropNode.childNodes;//嵌入类为目标节点的下的所有子节点
      }
      this.pCid.push(pCid);//存入单个最新父节点到内存
      //2、当前拖拽节点的最新顺序,
      for (let i = 0; i < siblings.length; i++) {
        if (siblings[i].data.catId == draggingNode.data.catId) {
          //到正在拖拽的节点时
          let catLevel = draggingNode.level;
          if (siblings[i].level != catLevel) {
            //当前节点的层级发生变化
            catLevel = siblings[i].level;
            //修改他子节点的层级
            this.updateChildNodeLevel(siblings[i]);
          }
          this.updateNodes.push({
            catId: siblings[i].data.catId,
            sort: i,
            parentCid: pCid,
            catLevel: catLevel
          });
        } else {
          this.updateNodes.push({ catId: siblings[i].data.catId, sort: i });
        }
      }
      //3、当前拖拽节点的最新层级
      console.log("updateNodes", this.updateNodes);
    },
    batchSave() {
      this.$http({
        url: this.$http.adornUrl("/product/category/update/sort"),
        method: "post",
        data: this.$http.adornData(this.updateNodes, false)
      }).then(({ data }) => {
        this.$message({
          message: "菜单顺序等修改成功",
          type: "success"
        });
        //刷新出新的菜单
        this.getMenus();
        //设置需要默认展开的菜单
        this.expandedKey = this.pCid;
        this.updateNodes = [];
        this.maxLevel = 0;
        // this.pCid = 0;
      });
    },
    updateChildNodeLevel(node) {
      if (node.childNodes.length > 0) {
        for (let i = 0; i < node.childNodes.length; i++) {
          var cNode = node.childNodes[i].data;
          this.updateNodes.push({
            catId: cNode.catId,
            catLevel: node.childNodes[i].level
          });
          this.updateChildNodeLevel(node.childNodes[i]);
        }
      }
    },
},

最终实现:完成拖拽限制,上传所有修改后数据,并展示当前展示的节点

流程分析

1.但用户拖拽并放在某个节点时,会先触发allowDrop,若判断为成功后触发handleDrop。

2.allowDrop解析:1.获得当前拖拽节点的最大深度+目标节点深度的两者之和,并根据拖拽的类型(内,并集,顺序调换)判断是否大于3

3.若深度没问题

静不下来,等上班再分析这段前端代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值