经验之谈:AntD级联选择动态加载数据

1,616 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情

前言

最近在将一个原生项目改版为Vue版本,进行了一些优化,既然用Vue,顺便使用antd作为ui,原生项目中地区选择我采用了多个选择框互联的方式实现,依次调用接口动态加载

20221013_224243.gif

这种需求大多数选择是做级联选择框,AntDesign中组件是Cascader,于是考虑做成级联选择框形式,查找AntDesign官方文档及案例,只提供了两级加载的案例

image.png

案例中一些参数也没有做过多的解释,那我三级甚至更多的级联选择应该怎么做呢?

实现

1. 数据格式

通过 children 多级嵌套

const options = [{
  value: 'jiangsu',
  label: 'Jiangsu',
  children: [{
    value: 'nanjing',
    label: 'Nanjing',
    children: [{
      value: 'zhonghuamen',
      label: 'Zhong Hua Men',
    }],
  }],
}];

2. 关键参数 fieldNames

作用:自定义字段名缩减代码量

如果没有合理使用,你的代码是这样的:

image.png

每一次获取分类数据时,都一直需要将服务端传过来的数据赋值给label, value等你所需要的字段,

用了 fieldNames 同名的字段会自动匹配,你的代码是这样的

image.png

image.png

简直事半功倍呀

一开始我没多想,寻思着这个字段就是要保证和后端数据一一对应的关系,重复工作丝毫未减,是我大冤种了。。。

3. isLeaf: false

在接口返回的数据中,如果后面还有字节点,添加参数 isLeaf: false,动态加载数据时,才会触发 loadData 方法,从而在 loadData 方法中请求下一级数据。 没有则设为true

后台数据没有该参数,需要对返回数据做进一步加工

4. loadData

作用: 动态加载选项

注意:loadData 与 showSearch 无法一起使用。

最关键的API,动态加载逻辑在这里

绑定 一个 loadData 方法

image.png

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]
    });
  }
}

4. 效果

20221013_224705.gif