谷粒商城 拖拽功能(前端)

准备

在这里插入图片描述

需求:点击拖拽功能后,拖拽树形数据,拖拽数据后,点击提交就会将拖拽完毕的信息自动保存到数据库

需求分析:

拖拽

有三种情况

  • inner: 拖拽到目的元素中
  • prev: 拖拽到目的元素前
  • next: 拖拽到目的元素后
判断

树形表只有三层,合并后如果大于三层,此操作应该不被允许

数据更新
  • 父节点不需要更新
  • 子节点需要更新 自己所在层数,父节点id,排序,以及它的子节点层数
  • 因为存在多次拖拽,更新和判断时需要以当前页面的数据为准,也就是Node数据
提交

因为是批量提交,所以需要修改的数据应该储存到一个全局数组中,在点击批量提交按钮后,会将所有节点数据一次性提交。

elementui组件

  • draggable true 为支持拖拽
  • :allow-drop="allowDrop" 是否允许被拖拽到当前位置 返回true表示不允许
  • @node-drop="handleDrop" 拖拽成功后调用

判断

最后的层数 = 被拖拽的节点总深度+拖入后父节点所在层数

  • 拖入后父节点
    inner: 目标节点
    else: 目标节点的父节点
  • 计算被拖拽元素的总层数,这里参考二叉树深度,用bfs
  getDepth(data) {
      let max = 0;
      if (data.children != null && data.children.length > 0) {
        for (let index = 0; index < data.children.length; index++) {
          max = Math.max(max, this.getDepth(data.children[index]));
        }
        return max + 1;
      }
      return 1;
  • 计算
  allowDrop(draggingNode, dropNode, type) { // 控制节点是否可以被拖拽
      let depth = this.getDepth(draggingNode.data); // 拖拽节点的总深度
      let level = dropNode.level; // 目的节点在第几层,这里的level使用node动态更新的level,因为存在批量拖拽,数据库中的数据不准确
      let sum = level + depth;  // 保证构建完毕后,总深度不大于3
      if (type == 'inner') {
        return sum <= 3;
      } else {
        return sum <= 4;// 并列关系是在父节点下层,所以是4
      }
    },

参数更新

动态加载的对象

  • Node.level 表示当前层级
  • Node.childNodes 表示当前节点的子节点
  • Node.parent 表示当前节点的父节点

我们需要做的就是根据动态加载的参数,将data中的属性赋值,最后加载到全局数组updateNodes中去。之后点击批量修改按钮,就可以将通过后端修改数据库。

层级和父节点id

inner 针对目的节点,其他的是目的节点的父节点。
在这里插入图片描述

排序

因为在拖动时Node中的children已经动态加载了,我们要做的就是将拖动节点父节点孩子打印出来,然后sort属性就是遍历的索引值(因为childNodes是按照当前页面的数据打印的)
注意:这次的更新要将目的节点的同级节点全部更新,因为目的节点的位置和同级节点是相关的

  sort(siblings) {
      for (let i = 0; i < siblings.length; i++) {
        const node = siblings[i];
        this.updateNodes.push({ catId: node.data.catId, parentCid: node.data.parentCid, catLevel: node.data.catLevel, sort: i });

      }
    },
递归修改目标节点的子节点

子节点也要添加到updateNodes中

   changeChildren(children) {  // 修改被拖拽的节点及其子节点 parentCid catLevel,将子节点添加到需要修改的节点中
      if (children != null && children.length > 0) {
        for (let i = 0; i < children.length; i++) {
          let node = children[i];
          this.updateNodes.push({ catId: node.data.catId, parentCid: node.data.parentCid, catLevel: node.data.catLevel });
          node.data.parentCid = node.parent.data.catId;
          node.data.catLevel = node.parent.data.catLevel + 1;
          this.changeChildren(node.childern);

        }
      }
    },
流程

在这里插入图片描述

代码

allowDrop

allowDrop(draggingNode, dropNode, type) { // 控制节点是否可以被拖拽
      let depth = this.getDepth(draggingNode.data); // 拖拽节点的总深度
      let level = dropNode.level; // 目的节点在第几层,这里的level使用node动态更新的level,因为存在批量拖拽,数据库中的数据不准确
      let sum = level + depth;  // 保证构建完毕后,总深度不大于3
      if (type == 'inner') {
        return sum <= 3;
      } else {
        return sum <= 4;// 并列关系是在父节点下层,所以是4
      }
    },

handleDrop

   handleDrop(draggingNode, dropNode, dropType, ev) {// 拖拽时改变的值,parentCid,catLevel,sort
      // 更新parentCid catLevel
      let siblings = dropNode.childNodes;
      if (dropType == 'inner') {  
        draggingNode.data.parentCid = dropNode.data.catId;
        draggingNode.data.catLevel = dropNode.level + 1;;
      } else {

        draggingNode.data.parentCid = dropNode.data.parentCid;
        draggingNode.data.catLevel = dropNode.level;
        siblings = dropNode.parent.childNodes;
      }
      // 排序
      this.sort(siblings, draggingNode);
      // 更新子节点
      this.changeChildren(draggingNode.childNodes);
      // 记录父节点的id,方便提交后展开
      this.pcids.push(draggingNode.data.parentCid);
      // 修改数据库
      // this.editCategories(this.updateNodes);
      // this.extendKey = [draggingNode.data.parentCid];
    },

editCategories

editCategories() {
      this.$http({
        url: this.$http.adornUrl('/product/category/update/list'),
        method: 'post',
        data: this.$http.adornData(this.updateNodes, false)
      }).then(({ data }) => {
        this.$message({
          message: "拖拽成功",
          type: "success",
        });
        this.getMenu();
        this.extendKey = this.pcids;
        this.updateNodes = []; //清空数据
        this.pcids = [];
      });
    },
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值