每天一点前端知识 - 遍历操作树

88 阅读1分钟

实现

const traverItem =
  fn =>
    (arr, childKey = 'children') => {
      if (!Array.isArray(arr)) {
        return arr;
      }
      const traver = (data, parent = []) =>
        data.map((item, k) => {
          const hasChild = Array.isArray(item[childKey]);
          item = fn(item, parent, k, hasChild) || item;
          if (hasChild) {
            const {[childKey]: children, ...rest} = item;
            item[childKey] = traver(children, [...parent, {...rest, '@@index': k}]);
          }
          return item;
        });
      return traver(arr);
    };

这是一个高阶函数,传入的 fn 函数可以获取当前树节点并进行操作,如修改属性、添加属性、针对个别属性进行处理等。

使用

traverItem((item, parent, index, hasChild) => {
  console.log(item, parent, index, hasChild);
})(arr, childKey);

- fn:回调函数
	- item:当前节点数据
	- parent:父节点数据
	- index:当前节点下标
	- hasChild:是否有子节点

- arr:树对象
- childKey:子节点 `key` 值,默认 `children`

示例

const routes = [
  {
    path: '/payer',
    name: '会员管理',
    icon: 'AccountBookOutlined',
    children: [
      {
        path: '/count',
        name: '包次会员',
        icon: 'FundViewOutlined',
        children: [
          {
            path: '/member',
            name: '开通会员',
            icon: 'ShoppingOutlined',
          },
          {
            path: '/order',
            name: '订单列表',
            icon: 'AuditOutlined',
          },
          {
            path: '/pay',
            name: '支付',
            icon: 'DollarOutlined',
            hideMenu: true,
          },
        ],
      },
      {
        path: '/month',
        name: '包月会员',
        icon: 'CoffeeOutlined',
        children: [
          {
            path: '/member',
            name: '开通会员',
            icon: 'ShoppingOutlined',
          },
          {
            path: '/order',
            name: '订单列表',
            icon: 'AuditOutlined',
          },
          {
            path: '/pay',
            name: '支付',
            icon: 'DollarOutlined',
            hideMenu: true,
          },
        ],
      },
    ],
  },
];
const callback = (item, parent, index, hasChild) => {
  item.fullpath = [...parent, item].map(item => item.path).join('');
  item.isLeaf = !hasChild;
  if (item.fullpath === '/payer/count/member') {
    item.icon = 'HaHa';
  }
  if (item.fullpath === '/payer/month/order') {
    item.hideMenu = true;
  }
  return item;
};
traverItem(callback)(routes);

4.png

4-result.png

演示地址:ihuxy.com/play?utils=…