树形结构

由于使用的element组件,所以最初是打算采用组件提供的
{ id: 2, label: '一级 2', children: [{ id: 5, label: '二级 2-1' }
这种数据结构形式,直接在前端渲染数据,然后调用 Tree 实例的filter方法过滤树节点,添加和删除节点的方式例子中也有直接说明,然后添加一个创建根节点的方法,如下:
在这里插入图片描述
点击添加栏目或者添加时,都会弹出一个弹出框,将弹出框的值存储进临时currentData 中:

<el-button icon="el-icon-circle-plus-outline" type="text" @click="appendNode(0)">添加栏目</el-button>

<div class="block">
        <el-input v-model="filterText" placeholder="请输入栏目名称" />
        <el-tree
          ref="tree"
          :data="data"
          show-checkbox
          node-key="id"
          default-expand-all
          :expand-on-click-node="false"
          :filter-node-method="filterNode"
          @node-click="changeData(data)"
        >
          <span slot-scope="{ node, data }" class="custom-tree-node">
            <span>{{ node.label }}</span>
            <span>
              <el-button type="text" size="mini" @click="() => appendNode(data)">添加</el-button>
              <el-button type="text" size="mini" @click="() => remove(node, data)">删除</el-button>
            </span>
          </span>
        </el-tree>
      </div>

//方法
appendNode(data) {
      this.AddColumnsData = {}
      this.currentData = data
      this.AddColumns = true
    },

弹出框点击确定按钮时,执行append方法,添加一行数据

<el-button type="primary" @click="append()">确 定</el-button>

 append() {
      this.AddColumns = false
      let id = 1000
      const newChild = {
        id: id++,
        label: this.AddColumnsData.title,
        children: []
      }
      if (this.currentData) {
        // 点击添加时执行
        if (!this.currentData.children) {
          this.$set(this.currentData, 'children', [])
        }
        this.currentData.children.push(newChild)
      } else {
        // 点击添加栏目时执行
        if (!this.data.children) {
          this.$set(this.data, 'children', [])
        }
        this.data.push(newChild)
      }
    },

由于性能优化问题,在查询时考虑时间复杂度问题,用children遍历以及树形传递数据的问题,将后端返回数据形式修改为前端进行处理,后端数据返回pid,前端处理

source = [{
                id: 1,
                pid: 0,
                name: 'body'
            }, {
                id: 2,
                pid: 1,
                name: 'title'
            }, {
                id: 3,
                pid: 2,
                name: 'div'
            }]
            
          //  修改为:
          datas: [
        {
          id: 1,
          pid: 0,
          name: "body",
          children: [
            {
              id: 2,
              pid: 1,
              name: "title",
              children: [
                {
                  id: 3,
                  pid: 1,
                  name: "div"
                }
              ]
            }
          ]
        }
      ]
						

  function toTree(data) {
              let result = [];
		      if (!Array.isArray(data)) {
		        return result;
		      }
		      data.forEach(item => {
		        delete item.children;
		      });
		      let map = {};
		      data.forEach(item => {
		        map[item.id] = item;
		      });
		      data.forEach(item => {
		        let parent = map[item.pid];
		        let label = "";
		        item.label = item.name;
		        if (parent) {
		          (parent.children || (parent.children = [])).push(item);
		          parent.children.forEach(_item => {
		            _item.label = item.name;//后端字段名为name
		          });
		        } else {
		          result.push(item);
		        }
		      });
		      return result;
            }

参考链接(侵删):
https://www.cnblogs.com/mengfangui/p/10494601.html
https://blog.csdn.net/susuzhe123/article/details/95353403

前端在一系列的操作后也需要将树再次转化,传到后端

jsonToArray(nodes) {
      var r = [];
      // console.log(nodes, "nodes");
      //需要将树中的label值去掉
      if (Array.isArray(nodes)) {
        for (var i = 0, l = nodes.length; i < l; i++) {
          r.push(nodes[i]); // 取每项数据放入一个新数组
          if (
            Array.isArray(nodes[i]["children"]) &&
            nodes[i]["children"].length > 0
          )
            // 若存在children则递归调用,把数据拼接到新数组中,并且删除该children
            r = r.concat(this.jsonToArray(nodes[i]["children"]));
          delete nodes[i]["children"];
        }
      }
      return r;
    },

在这个过程中,需要深度拷贝,否则数据会受到干扰,不能出现正常结果。

参考链接:https://blog.csdn.net/qq_39009348/article/details/87365547

现在append方法需要在增加一个节点的时候,将pid的值绑定上去,修改方法如下:

async append() {
      this.AddColumns = false;
      console.log(this.currentData);
      const newChild = {
        label: this.AddColumnsData.title,
        children: [],
        createdDate: "",
        groupCode: 0,
        name: this.AddColumnsData.title,
        orders: 0,
        organizationCode: 0,
        pid: this.currentData.id,
        target: this.AddColumnsData.target,
        updatedDate: "",
        url: this.AddColumnsData.url
      };
      if (this.currentData) {
        // 点击添加时执行
        if (!this.currentData.children) {
          this.$set(this.currentData, "children", []);
        }
        this.currentData.children.push(newChild);
        await save(newChild);
      } else {
        // 点击添加栏目时执行
        if (!this.data.children) {
          this.$set(this.data, "children", []);
        }
        this.data.push(newChild);
        await save(newChild);
      }
    },

这样就完成了增加子节点功能,然后需要勾选节点时,删除节点,增加以下方法:

<el-tree
          ref="tree"
          :data="data"
          show-checkbox
          node-key="id"
          default-expand-all
          :expand-on-click-node="false"
          :filter-node-method="filterNode"
          @node-click="changeData(data)"
          @check-change="handleCheckChange"
        >
</el-tree>

//勾选复选框时触发
    handleCheckChange() {
      let res = this.$refs.tree.getCheckedNodes();
      res.forEach(item => {
        this.currentTreeData += item.id + ";";
      });
    }

参考链接:https://blog.csdn.net/LLL_liuhui/article/details/88963616

树形结构到这里应该结束了,但是今天来测试的时候发现了一个问题

由于id是从后台获取 所以每次在新添加的节点下添加节点时需要刷新后才能添加,要不然无法获取到id值作为下一级的pid

解决方案:每次添加节点后就刷新

解决方案每次刷新用户体验感不太好,等写完再寻找更好的解决方案

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

echo忘川

谢谢老板们

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值