vant中的Cascader級聯(lián)選擇異步加載地區(qū)數(shù)據(jù)方式
使用vant的Cascader級聯(lián)選擇異步加載地區(qū)數(shù)據(jù)
需求
因?yàn)槿珖貐^(qū)數(shù)據(jù)太多,如果要一次加載出來,再顯示頁面會比較慢。所以通過接口點(diǎn)擊獲取當(dāng)前的數(shù)據(jù)
需要注意的點(diǎn)
- 后臺接口在返回?cái)?shù)據(jù)時(shí),如果有下一級的數(shù)據(jù),要讓后臺返回children,如果不返回,控件就會出現(xiàn)關(guān)閉彈框無法點(diǎn)擊下一級的bug(控件是根據(jù)是否有children來判斷是否要繼續(xù)點(diǎn)擊的,前端是無法知道是否存在下一級數(shù)據(jù)的)
- 添加數(shù)據(jù)的3種方案任選一種就可以,推薦第一種,無論多少層級都可以添加上。第二種只判斷了4級的添加,5級數(shù)據(jù)添加不上,第三種是遞歸的方式添加數(shù)據(jù)
<van-cascader v-model="cascaderValue" title="請選擇所在地區(qū)" :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' }, // 選項(xiàng)列表,children 代表子選項(xiàng),支持多級嵌套 options: [], divisionIds: '', // 地區(qū)的id divisionNames: '', // 地區(qū)的名字 } },
第一種方案
比較簡單,vant中觸發(fā)本身的change事件,可以拿到當(dāng)前點(diǎn)擊的元素,以及它的上層元素,我們只需要把請求到的最新數(shù)據(jù),加在最里面的數(shù)據(jù)結(jié)構(gòu)中即可
methods: { // 級聯(lián)數(shù)據(jù)全部選項(xiàng)選擇完畢后,會觸發(fā) finish 事件 onFinish({ selectedOptions }) { this.divisionNames = selectedOptions.map(option => option.name).join('/') this.divisionIds = selectedOptions.map(option => option.id).join(',') this.areaShow = false }, // 從接口請求獲取第一層的數(shù)據(jù),---比如北京 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// 這個(gè)很關(guān)鍵 }) }) }, onChangeArea({ value, selectedOptions, tabIndex }) { // 需要后臺接口返回children數(shù)據(jù) // 拿到數(shù)據(jù)后,動(dòng)態(tài)添加 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: { // 級聯(lián)數(shù)據(jù)全部選項(xiàng)選擇完畢后,會觸發(fā) finish 事件 onFinish({ selectedOptions }) { this.divisionNames = selectedOptions.map(option => option.name).join('/') this.divisionIds = selectedOptions.map(option => option.id).join(',') this.areaShow = false }, // 從接口請求獲取第一層的數(shù)據(jù),---比如北京 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// 這個(gè)很關(guān)鍵 }) }) }, onChangeArea({ value, selectedOptions, tabIndex }) { // 需要后臺接口返回children數(shù)據(jù) // 拿到數(shù)據(jù)后,動(dòng)態(tài)添加 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 // 城市下的城區(qū) let index = areas.findIndex(item => item.id === value) // 城區(qū) index areas[index].children = res.data // this.$set(this.options[firstIndex].children[secondIndex].children[index], 'children', res.data) } }) }, }
第三種方案
// 級聯(lián)數(shù)據(jù)全部選項(xiàng)選擇完畢后,會觸發(fā) finish 事件 onFinish({ selectedOptions }) { this.divisionNames = selectedOptions.map(option => option.name).join('/') this.divisionIds = selectedOptions.map(option => option.id).join(',') this.areaShow = false }, // 從接口請求獲取第一層的數(shù)據(jù),---比如北京 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// 這個(gè)很關(guān)鍵 }) }) }, onChangeArea({ value, selectedOptions, tabIndex }) { // 需要后臺接口返回children數(shù)據(jù) // 拿到數(shù)據(jù)后,動(dòng)態(tài)添加 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) } }
- 第一次獲取到的數(shù)據(jù)
- 點(diǎn)擊山東省后獲取的數(shù)據(jù)
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Vue實(shí)現(xiàn)阻止瀏覽器記住密碼功能的三種方法
本文主要介紹了Vue實(shí)現(xiàn)阻止瀏覽器記住密碼功能的三種方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06Vue 對象和數(shù)據(jù)的強(qiáng)制更新方式
這篇文章主要介紹了Vue 對象和數(shù)據(jù)的強(qiáng)制更新方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04electron?dialog.showMessageBox的使用案例
Electron?Dialog?模塊提供了api來展示原生的系統(tǒng)對話框,本文主要介紹了electron?dialog.showMessageBox的使用案例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08詳解element-ui日期時(shí)間選擇器的日期格式化問題
這篇文章主要介紹了詳解element-ui日期時(shí)間選擇器的日期格式化問題,本文用到了DateTimePicker來選擇日期時(shí)間,但是在將數(shù)據(jù)傳回后臺的過程中遇到了一些令人頭疼的問題,有興趣的一起來了解一下2019-04-04vue中實(shí)現(xiàn)子組件接收父組件方法并獲取返回值
這篇文章主要介紹了vue中實(shí)現(xiàn)子組件接收父組件方法并獲取返回值方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08