vant中的Cascader级联选择异步加载地区数据方式
作者:Fighting宁
这篇文章主要介绍了vant中的Cascader级联选择异步加载地区数据方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
使用vant的Cascader级联选择异步加载地区数据
需求
因为全国地区数据太多,如果要一次加载出来,再显示页面会比较慢。所以通过接口点击获取当前的数据
需要注意的点
- 后台接口在返回数据时,如果有下一级的数据,要让后台返回children,如果不返回,控件就会出现关闭弹框无法点击下一级的bug(控件是根据是否有children来判断是否要继续点击的,前端是无法知道是否存在下一级数据的)
- 添加数据的3种方案任选一种就可以,推荐第一种,无论多少层级都可以添加上。第二种只判断了4级的添加,5级数据添加不上,第三种是递归的方式添加数据
<van-cascader v-model="cascaderValue" title="请选择所在地区" :options="options" @close="areaShow = false" @finish="onFinish" :field-names="fieldNames" @change="onChangeArea" />
需要用到的data中的变量
export default { data() { return { areaShow: false, cascaderValue: '', fieldNames: { text: 'name', value: 'id', children: 'children' }, // 选项列表,children 代表子选项,支持多级嵌套 options: [], divisionIds: '', // 地区的id divisionNames: '', // 地区的名字 } },
第一种方案
比较简单,vant中触发本身的change事件,可以拿到当前点击的元素,以及它的上层元素,我们只需要把请求到的最新数据,加在最里面的数据结构中即可
methods: { // 级联数据全部选项选择完毕后,会触发 finish 事件 onFinish({ selectedOptions }) { this.divisionNames = selectedOptions.map(option => option.name).join('/') this.divisionIds = selectedOptions.map(option => option.id).join(',') this.areaShow = false }, // 从接口请求获取第一层的数据,---比如北京 async getAreaList() { let id = '' let res = await getAreaList(id) res.data.forEach(item => { this.options.push({ name: item.name, id: item.id, children: item.children || null// 这个很关键 }) }) }, onChangeArea({ value, selectedOptions, tabIndex }) { // 需要后台接口返回children数据 // 拿到数据后,动态添加 getAreaList(value).then(res => { // 第一种方案 this.addTree(selectedOptions, res.data, value) }) }, addTree(selectedOptions, children, id) { selectedOptions.forEach(item => { if (item.id === id) { item.children = children } }) } } }
第二种方案:不推荐
methods: { // 级联数据全部选项选择完毕后,会触发 finish 事件 onFinish({ selectedOptions }) { this.divisionNames = selectedOptions.map(option => option.name).join('/') this.divisionIds = selectedOptions.map(option => option.id).join(',') this.areaShow = false }, // 从接口请求获取第一层的数据,---比如北京 async getAreaList() { let id = '' let res = await getAreaList(id) res.data.forEach(item => { this.options.push({ name: item.name, id: item.id, children: item.children || null// 这个很关键 }) }) }, onChangeArea({ value, selectedOptions, tabIndex }) { // 需要后台接口返回children数据 // 拿到数据后,动态添加 getAreaList(value).then(res => { // 第二种方案 if (tabIndex === 0) { let index = this.options.findIndex(item => item.id === value) this.options[index].children = res.data // this.$set(this.options[index], 'children', res.data) } else if (tabIndex === 1) { let firstIndex = this.options.findIndex(item => item.id === selectedOptions[0].id) // 省级 index let cities = this.options[firstIndex].children // 所有城市 let index = cities.findIndex(item => item.id === value) // 市级 index cities[index].children = res.data // this.$set(this.options[firstIndex].children[index], 'children', res.data) } else if (tabIndex === 2) { let firstIndex = this.options.findIndex(item => item.id === selectedOptions[0].id) // 省级 index let cities = this.options[firstIndex].children // 所有城市 let secondIndex = cities.findIndex(item => item.id === selectedOptions[1].id) // 市级 index let areas = cities[secondIndex].children // 城市下的城区 let index = areas.findIndex(item => item.id === value) // 城区 index areas[index].children = res.data // this.$set(this.options[firstIndex].children[secondIndex].children[index], 'children', res.data) } }) }, }
第三种方案
// 级联数据全部选项选择完毕后,会触发 finish 事件 onFinish({ selectedOptions }) { this.divisionNames = selectedOptions.map(option => option.name).join('/') this.divisionIds = selectedOptions.map(option => option.id).join(',') this.areaShow = false }, // 从接口请求获取第一层的数据,---比如北京 async getAreaList() { let id = '' let res = await getAreaList(id) res.data.forEach(item => { this.options.push({ name: item.name, id: item.id, children: item.children || null// 这个很关键 }) }) }, onChangeArea({ value, selectedOptions, tabIndex }) { // 需要后台接口返回children数据 // 拿到数据后,动态添加 getAreaList(value).then(res => { // 第三种方案 this.addTree1(res.data, value) }) }, // 递归写法 addTree1(list, value) { function addTree2(json, id) { const index = json.findIndex(ev => ev.id == id) if (index > -1) { json[index].children = list return } else { json.map(item => { if (item.children) { addTree2(item.children || [], value) } }) } } addTree2(this.options, value) } }
- 第一次获取到的数据
- 点击山东省后获取的数据
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。