antd 级联选择器Cascader(或TreeSelect树选择器 )如何仅根据最后一级value回显完整中文路径
antd 级联选择器Cascader(或TreeSelect树选择器 )如何仅根据最后一级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(<Cascader options={options} onChange={onChange} />, mountNode);
在选中Zhejiang / Hangzhou / Wes tLake时,对应的value是['zhejiang', 'hangzhou', 'xihu']
,后端可能只需要你传递xihu
即可,而非数组形式的网站路径信息。
这时前端在回显的时候会出现一个问题,无法根据xihu
完整的回显之前的路径名Zhejiang / Hangzhou / Wes tLake了。
如何收集完整的节点路径信息
我们可以借助官网在TreeSelect给的提示onChange时如何获得父节点信息?
其思路就是将节点value作为对象valueMap
的key,遍历节点的子节点children(如果有的话),通过parent该节点和其子节点链接起来。后续就可以用getPath
方法根据value
在valueMap
通过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(' / ') })}
因为fullLabelPath
是useMemo
的返回值,valueMap
是useState
的返回值,这样我们也不必担心列表数据渲染时Cascader的valueMap
还未收集好的情况了,待valueMap
收集完毕后,自会重新渲染的。
同样的思路也可以用在TreeSelect树选择器,我就不具体写了哦。
- 分类:
- Web前端