antd Cascader(或TreeSelec )仅根据最后一级value回显完整路径

Cascader(或TreeSelect树选择器 )往往会在项目中用在分类管理这一需求,可以很好的展示分类的层级结构,有时可能因为分类会存在改变层级(如由四级分类变成了二级分类)的情况,后端接口会要求在存储分类数据的时候,仅传递最后一级的信息。

例子

举个antd官网的例子:

import { Cascader } from 'antd';

const options = [
  {
    value: 'zhejiang',
    label: 'Zhejiang',
    children: [
      {
        value: 'hangzhou',
        label: 'Hangzhou',
        children: [
          {
            value: 'xihu',
            label: 'West Lake',
          },
        ],
      },
    ],
  },
  {
    value: 'jiangsu',
    label: 'Jiangsu',
    disabled: true,
    children: [
      {
        value: 'nanjing',
        label: 'Nanjing',
        children: [
          {
            value: 'zhonghuamen',
            label: 'Zhong Hua Men',
          },
        ],
      },
    ],
  },
];

function onChange(value) {
  console.log(value);
}

ReactDOM.render(, mountNode);

在选中Zhejiang / Hangzhou / Wes tLake时,对应的value是['zhejiang', 'hangzhou', 'xihu'],后端可能只需要你传递xihu即可,而非数组形式的网站路径信息。

这时前端在回显的时候会出现一个问题,无法根据xihu完整的回显之前的路径名Zhejiang / Hangzhou / Wes tLake了。

如何收集完整的节点路径信息

我们可以借助官网在TreeSelect给的提示onChange时如何获得父节点信息?

其思路就是将节点value作为对象valueMap的key,遍历节点的子节点children(如果有的话),通过parent该节点和其子节点链接起来。后续就可以用getPath方法根据valuevalueMap通过parent一层一层找到对应的父节点信息了。

const valueMap = {};
function loops(list, parent) {
  return (list || []).map(({ children, value, label }) => {
    const node = (valueMap[value] = {
      parent,
      data: {
        label,
        value
      }
    });
    node.children = loops(children, node);
    return node;
  });
}

loops(treeData);

function getPath(value, prop) {
  const path = [];
  let current = valueMap[value];
  while (current) {
    path.unshift(current.data[prop]);
    current = current.parent;
  }
  return path;
}

简单改造下,同时valueMap同时收集下lable信息,同时getPath支持返回指定prop的信息,让回显更加灵活。

如何使用getPath完成数据

方法一:我们可以直接通过ref暴露出去

useImperativeHandle(ref, () => ({ valueMap, getPath, }))

但是这样在部分使用起来不合适,比如列表展示时,并且这样也会存在因为列表数据渲染时`Cascader`的`valueMap`还未收集好,而`getPath`获取结果为空的情况。

我们可以试试方法二

方法二:支持自定义render

function CategorySelect(props, ref) {
  const [value, setValue] = useState([]);
  const [valueMap, setValueMap] = useState({});
  // 根据value回显对应的label
  const fullLabelPath = useMemo(() => {
    if (!props.displayLabel) {
      return;
    }
    return getPath(props.value, props.displayLabel);
  }, [props.displayLabel, props.value, props.data, valueMap]);

  ...

  return {
    (props.fullLabelRender)
      ? props.fullLabelRender(fullLabelPath)
      : (
          
        )
  }
}

我们将全路径的渲染能力开放通过`props.fullLabelRender`

使用可以这样使用

fullLabelRender={(fullLabelPath) => ({ fullLabelPath.join(' / ') })}

因为fullLabelPathuseMemo的返回值,valueMapuseState的返回值,这样我们也不必担心列表数据渲染时Cascader的valueMap还未收集好的情况了,待valueMap收集完毕后,自会重新渲染的。

同样的思路也可以用在TreeSelect树选择器,我就不具体写了哦。

展开阅读全文

页面更新:2024-05-13

标签:路径   层级   节点   例子   思路   完整   情况   方法   数据   列表   信息

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top