vue 树形菜单目录的实现思路;自己对于 js arrary.filter() 的理解。

  1. 菜单表 menu_id, parent_id,order_num
  2. 查询给前端的 select menu_id,parent_id,order_num from menu order by parent_id,order_menu
  3. 前端处理
    参数说明 :
    data :获取的数组
    id: 比如 menu_id
    后面的可以不传。

示例数组(后台查出):

[
    {menu_id: 1, parent_id:0 ,order_id:0},
    {menu_id: 2, parent_id:0 ,order_id:1},
    {menu_id: 3, parent_id:0 ,order_id:2},
    {menu_id: 4, parent_id:0 ,order_id:3},
    {menu_id: 5, parent_id:3 ,order_id:0},
    {menu_id: 6, parent_id:4 ,order_id:0},
    {menu_id: 7, parent_id:5 ,order_id:0},
    {menu_id: 8, parent_id:5 ,order_id:1}
]

前端 js 的一个处理函数

export function handleTree(data, id, parentId, children, rootId) {
	id = id || 'id'
	parentId = parentId || 'parentId'
	children = children || 'children'
	rootId = rootId || 0
	//对源数据深度克隆
	const cloneData = JSON.parse(JSON.stringify(data))
	//循环所有项
	const treeData =  cloneData.filter(father => {
	  let branchArr = cloneData.filter(child => {
		//返回每一项的子级数组
		return father[id] === child[parentId]
	  });
	  branchArr.length > 0 ? father.children = branchArr : '';
	  //返回第一层
	  return father[parentId] === rootId;
	});
	return treeData != '' ? treeData : data;
  }

注: 我的前端比较菜,对 filter() 不了解,理了好半天才反应过来。

总结:
首先最里面的 child 过滤。 将所循环到的 节点的 子节点安排上了。
这个时候可以认为, 每个节点都是地址引用。只要有,就可以找到 N 级菜单。
最外面的 father 过滤就一个功能。干掉 父节点不是 0 的。 或者是你自己设置的根节点的值。

下面是具体示例数据的分析:

当 : menu_id ==4 的时候。把 子节点 5 加到 4 上面。

[
    {menu_id: 1, parent_id:0 ,order_id:0},
    {menu_id: 2, parent_id:0 ,order_id:1},
    {menu_id: 3, parent_id:0 ,order_id:2 ,children: [
        {menu_id: 5, parent_id:3 ,order_id:0}
    ]},
    {menu_id: 4, parent_id:0 ,order_id:3 ,children: [
        {menu_id: 6, parent_id:4 ,order_id:0}
    ]},
    {menu_id: 5, parent_id:3 ,order_id:0},
    {menu_id: 6, parent_id:4 ,order_id:0},
    {menu_id: 7, parent_id:5 ,order_id:0},
    {menu_id: 8, parent_id:5 ,order_id:1}
]

在 menu_id == 5 没返回之前。
此时 5 已经有了子元素 7,8 。
所以从 3 可以找到 7,8 。
可以理解为地址引用。
也就是说 3 实际存放的是 5 所在的内存地址。而 5 中也是同样的存了 7,8 的地址。

[
    {menu_id: 1, parent_id:0 ,order_id:0},
    {menu_id: 2, parent_id:0 ,order_id:1},
    {menu_id: 3, parent_id:0 ,order_id:2 ,children: [
        {menu_id: 5, parent_id:3 ,order_id:0 ,children:[
            {menu_id: 7, parent_id:5 ,order_id:0},
            {menu_id: 8, parent_id:5 ,order_id:1}
        ]}
    ]},
    {menu_id: 4, parent_id:0 ,order_id:3 ,children: [
        {menu_id: 6, parent_id:4 ,order_id:0}
    ]},
    {menu_id: 5, parent_id:3 ,order_id:0 ,children:[
        {menu_id: 7, parent_id:5 ,order_id:0},
        {menu_id: 8, parent_id:5 ,order_id:1}
    ]},
    {menu_id: 6, parent_id:4 ,order_id:0},
    {menu_id: 7, parent_id:5 ,order_id:0},
    {menu_id: 8, parent_id:5 ,order_id:1}
]

menu_id == 5 返回之后,因为 5 的父节点不是 0 , 故 5 没了。

[
    {menu_id: 1, parent_id:0 ,order_id:0},
    {menu_id: 2, parent_id:0 ,order_id:1},
    {menu_id: 3, parent_id:0 ,order_id:2 ,children: [
        {menu_id: 5, parent_id:3 ,order_id:0 ,children:[
            {menu_id: 7, parent_id:5 ,order_id:0},
            {menu_id: 8, parent_id:5 ,order_id:1}
        ]}
    ]},
    {menu_id: 4, parent_id:0 ,order_id:3 ,children: [
        {menu_id: 6, parent_id:4 ,order_id:0}
    ]},
    {menu_id: 6, parent_id:4 ,order_id:0},
    {menu_id: 7, parent_id:5 ,order_id:0},
    {menu_id: 8, parent_id:5 ,order_id:1}
]

最终达到的效果是:

[
    {menu_id: 1, parent_id:0 ,order_id:0},
    {menu_id: 2, parent_id:0 ,order_id:1},
    {menu_id: 3, parent_id:0 ,order_id:2 ,children: [
        {menu_id: 5, parent_id:3 ,order_id:0 ,children:[
            {menu_id: 7, parent_id:5 ,order_id:0},
            {menu_id: 8, parent_id:5 ,order_id:1}
        ]}
    ]},
    {menu_id: 4, parent_id:0 ,order_id:3 ,children: [
        {menu_id: 6, parent_id:4 ,order_id:0}
    ]}
]

记录一些思路:

按照上面设计表来说呢:
是不去存储父级元素名称的。遇到如下情况时(需要去展示父级元素名称),前端怎么办?
在这里插入图片描述
图 0
首先明确一点,在点出详情页的时候,是做了一次查询的。为什么呢?表格中的数据不一定够。而且有可能详情展示涉及其他表的更具体的信息,所以,详情查询一次是非常好的方案。
既然查询了。就可以要求后端给出 parentName 。

如果表格数据一定够的话,减少查询时非常好的选择。这个时候就需要保存一下我们调用 handleTree 之前的 数组。 根据 父节点id 利用 filter 过滤出 父节点名称。
总的思路是这样的:

// 在 created() 中,调用 getList() 在得到参数的时候,保存两个数组。 一个时表格绑定的数组(classifyList ),另外一个就是查询到的一维数组(querayData)。
 /** 查询国家分类列表 */
    getList() {
      this.loading = true;
      listClassify(this.queryParams).then(response => {
        this.querayData = response.rows;
        this.classifyList = this.handleTree(response.rows, "id", "parentId", "children", "0");
        this.total = response.total;
        this.loading = false;
      });
    },

但是此时出现一个问题。例如 图 2 .
我在点击搜素的时候调用的 也是 getList()
这个时候,queryData 变化了。不是全部数据了。只是一个子集。例如图 3 。 后面再使用这个数组去根据 Id 过滤名称就没有意义了。
此时在查询函数中为 queryData 的赋值做一个条件判断。
非全部查询,就不赋值给 queryData 。

    /** 查询国家分类列表 */
    getList() {
      this.loading = true;
      console.log(this.queryParams)
      listClassify(this.queryParams).then(response => {
        if (this.queryParams.name == undefined && this.queryParams.classifyLevel == undefined && this.queryParams.parentId == undefined && this.queryParams.sort == undefined) {
          this.querayData = response.rows;
        }
        this.classifyList = this.handleTree(response.rows, "id", "parentId", "children", "0");
        this.total = response.total;
        this.loading = false;
      });
    },

当然,判断条件过多或者说不好判断的时候。也可以单独写一个全部查询,只在页面创建的时候调用一次。

树形菜单
图 1
表格树形菜单
图 2

表格树形菜单
图 3

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值