写在开头:项目的框架是vue+vant,业务需求一个级联的地区选择,写完才发现vant本身也有这组件....后来看vant本身用的逻辑跟我不太一样,觉得还有点思考价值那就发上来当做实现记录吧~

总体思路(select与tabs独立):

  1. 列表选择(select)
    1)获取当前tabs的长度 -> 设置当前active的name
    2)通过levelCollect(最终选择的数据集)设置每个层级,例:['第一层数据','第二层数据','第三层数据',...]
    3)删除后级数据,更新tabs长度
    4)如果有下级,新增active并选中,如果没有设置完成
  2. tab选择(tabsClick)
    1)拷贝一次原始数据,设置列表筛选数据:0级使用原始数据,其它选用存储数据设置高亮
    2)滚动到选中

目前功能支持:
·自定义数据
·N级数据联动
·上级数据选择后修改
·选择项高亮
todo:
数据回填

效果图:
image
addressCard.vue

<template>
  <div class="addressWrapper">
    <h4>请选择所在地区</h4>
    <div class="tabs">
        <van-tabs ref='tabs' v-model="active" scrollspy :ellipsis='false' @click='tabsClick' >
            <van-tab v-for="(tabItem,i) in tabsData" :title="tabItem.name" :key='i'>.</van-tab>
        </van-tabs>
        <div class="content">
            <div :class="['item',{select:item.select}]" v-for="(item,j) in areaJson" :key='j' @click='select(item)'>
                
                {{item.name}}
            </div>
        </div>
        
    </div>
  </div>
</template>

<script>
import { Tab,Tabs } from 'vant';
import areaJson from './areaJson/pcas-code.json'
export default {
  components: {
    [Tab.name]: Tab,
    [Tabs.name]:Tabs
  },
  data(){
      return{
          active:1,
          levelCollect:[],
          originArea:areaJson,
          areaJson,
          tabsData:[{
              name:'请选择'
          }]
      }
  },
  created(){
     
  },
  methods:{
      select(item){
          
          // 获取当前tabs的长度
          let len = this.tabsData.length
          // 设置当前active的name
          this.tabsData[this.active].name = item.name
         
          // 设置每个层级
          this.levelCollect[this.active] = item
         
          if(this.active<len){
              // 删除后部的城镇
              this.tabsData.splice(this.active+1)
              // 更新tabs长度
              len = this.tabsData.length
          }
          // 如果有下级,新增active并选中
          if(item.children){
              this.tabsData.push({name:'请选择'})
              // this.active = len
              this.$refs.tabs.scrollTo(len)
              this.areaJson = item.children
          }else{
              this.tabsClick(this.active,item.name)
          }
          
          
          
      },
      tabsClick(name,title){
          // 设置列表筛选数据:0级使用原始数据,其它选用存储数据设置高亮
          if(name===0){
              this.areaJson = this.originArea.slice().map(item=>{
                  return {
                      ...item,
                      select:item.name===title
                  }
              })
          }else{
              this.areaJson = this.levelCollect[name-1].children.map(item=>{
                  return {
                      ...item,
                      select:item.name===title
                  }
              })
          }
          // 滚动到选中
          this.$nextTick(()=>{
              let doc = document.querySelector('.select')
              doc&&doc.scrollIntoView();
          })
          
      }
  }
};
</script>

<style lang="less" scoped>
.addressWrapper {
  padding:20px 10px;
  h4{
      text-align:center;
  }
  .tabs{
    margin-top:20px;
    /deep/.van-tabs__content{
        display: none;
    }
    .content{
        margin-top:20px;
        height: 200px;
        overflow: scroll;
        .item{
            line-height:40px;
            font-size:14px;
            &.select{
                color:red;
            }
        }
    }
    
  }
}
</style>

附上本文中地区pcas-code.json数据:
https://github.com/modood/Administrative-divisions-of-China/blob/master/dist/pcas-code.json


quanta
17 声望3 粉丝

no bug