持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情
前言
最近在将一个原生项目改版为Vue版本,进行了一些优化,既然用Vue,顺便使用antd作为ui,原生项目中地区选择我采用了多个选择框互联的方式实现,依次调用接口动态加载
这种需求大多数选择是做级联选择框,AntDesign中组件是Cascader,于是考虑做成级联选择框形式,查找AntDesign官方文档及案例,只提供了两级加载的案例
案例中一些参数也没有做过多的解释,那我三级甚至更多的级联选择应该怎么做呢?
实现
1. 数据格式
通过 children 多级嵌套
const options = [{
value: 'jiangsu',
label: 'Jiangsu',
children: [{
value: 'nanjing',
label: 'Nanjing',
children: [{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
}],
}],
}];
2. 关键参数 fieldNames
作用:自定义字段名缩减代码量
如果没有合理使用,你的代码是这样的:
每一次获取分类数据时,都一直需要将服务端传过来的数据赋值给label
, value
等你所需要的字段,
用了 fieldNames 同名的字段会自动匹配,你的代码是这样的
简直事半功倍呀
一开始我没多想,寻思着这个字段就是要保证和后端数据一一对应的关系,重复工作丝毫未减,是我大冤种了。。。
3. isLeaf: false
在接口返回的数据中,如果后面还有字节点,添加参数 isLeaf: false,动态加载数据时,才会触发 loadData 方法,从而在 loadData 方法中请求下一级数据。 没有则设为true
后台数据没有该参数,需要对返回数据做进一步加工
4. loadData
作用: 动态加载选项
注意:loadData
与 showSearch
无法一起使用。
最关键的API,动态加载逻辑在这里
绑定 一个 loadData 方法
const loadData = (selectedOptions) => {
const targetOption = selectedOptions[selectedOptions.length - 1]
// 加载标识
targetOption.loading = true
if(targetOption.level === "county"){
apiAreaStreet({ county: targetOption.value }).then((res) => {
targetOption.loading = false
targetOption.children = res
options.value = [...options.value] // 重新赋值刷新数据
});
}else {
apiAreaStreet({ street: targetOption.value }).then((res) => {
targetOption.loading = false
targetOption.children = res
options.value = [...options.value]
});
}
}
由于动态加载多层,可以根据 targetOption 点击选项中的参数 加一些判断条件 区分层级
完整代码
1. HTML添加组件
<a-cascader
v-model:value="searchVal"
:options="options"
:field-names="{label: 'value', value: 'value', level: 'level', children:'children'}"
:load-data="loadData"
placeholder="请选择区域"
change-on-select
/>
2. 获取初始化数据
const options = ref([]);
const getAreaCity = (city) => {
apiAreaCity({ city }).then((res) => {
console.log(res)
options.value = res
});
};
3. 级联加载数据
const loadData = (selectedOptions) => {
console.log(selectedOptions)
const targetOption = selectedOptions[selectedOptions.length - 1]
// 加载标识
targetOption.loading = true
console.log('selectedOptions', selectedOptions)
console.log('targetOption', targetOption)
if(targetOption.level === "county"){
apiAreaStreet({ county: targetOption.value }).then((res) => {
targetOption.loading = false
targetOption.children = res
options.value = [...options.value]
});
}else {
apiAreaStreet({ street: targetOption.value }).then((res) => {
targetOption.loading = false
targetOption.children = res
options.value = [...options.value]
});
}
}