vant中的Cascader级联选择异步加载地区数据方式

 更新时间:2024年07月02日 08:36:59   作者: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)
    }
}
  • 第一次获取到的数据

  • 点击山东省后获取的数据

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Vuepress使用vue组件实现页面改造

    Vuepress使用vue组件实现页面改造

    这篇文章主要为大家介绍了Vuepress使用vue组件实现页面改造示例过程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-07-07
  • vue项目引入百度地图BMapGL鼠标绘制和BMap辅助工具

    vue项目引入百度地图BMapGL鼠标绘制和BMap辅助工具

    这篇文章主要为大家介绍了vue项目引入百度地图BMapGL鼠标绘制和BMap辅助工具的踩坑分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-02-02
  • vant中的Cascader级联选择异步加载地区数据方式

    vant中的Cascader级联选择异步加载地区数据方式

    这篇文章主要介绍了vant中的Cascader级联选择异步加载地区数据方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • ubuntu中利用nginx部署vue项目的完整步骤

    ubuntu中利用nginx部署vue项目的完整步骤

    Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行,下面这篇文章主要给大家介绍了关于ubuntu中利用nginx部署vue项目的相关资料,需要的朋友可以参考下
    2022-02-02
  • 前端在el-dialog中嵌套多个el-dialog代码实现

    前端在el-dialog中嵌套多个el-dialog代码实现

    最近使用vue+elementUI做项目,使用过程中很多地方会用到dialog这个组件,有好几个地方用到了dialog的嵌套,下面这篇文章主要给大家介绍了关于前端在el-dialog中嵌套多个el-dialog代码实现的相关资料,需要的朋友可以参考下
    2024-01-01
  • 详解Vue.js3.0 组件是如何渲染为DOM的

    详解Vue.js3.0 组件是如何渲染为DOM的

    这篇文章主要介绍了详解Vue.js3.0 组件是如何渲染为DOM的 ,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • element-ui 本地化使用教程详解

    element-ui 本地化使用教程详解

    这篇文章主要介绍了element-ui 本地化使用教程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • vue3项目打包成apk(android)详细图文教程

    vue3项目打包成apk(android)详细图文教程

    Vue本身是一个构建用户界面的渐进式框架,不能直接打包成APK文件,但是你可以使用工具将Vue应用打包成一个可以在Android设备上安装的APK文件,这篇文章主要给大家介绍了关于vue3项目打包成apk(android)的相关资料,需要的朋友可以参考下
    2024-05-05
  • npm如何更新VUE package.json文件中依赖的包版本

    npm如何更新VUE package.json文件中依赖的包版本

    这篇文章主要介绍了npm如何更新VUE package.json文件中依赖的包版本问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • 一文了解Vue中的nextTick

    一文了解Vue中的nextTick

    Vue中的 nextTick 涉及到Vue中DOM的异步更新,感觉很有意思,特意了解了一下。其中关于 nextTick 的源码涉及到不少知识,很多不太理解,暂且根据自己的一些感悟介绍下 nextTick
    2019-05-05

最新评论