移动端基于vant的可自定义的多级联动选择框

省市区三级联动已无法满足项目需要 故修改选择方式及效果 修改后的效果如下 用到了vant的tabs 在这里插入图片描述

级别可无限增加 支持反向渲染
子集字段children

html

<van-tabs v-model="active" ref="vanTab" color="rgb(30, 136, 245)">
 <van-tab :title="item.title" v-for="(item,index) in list" :key="index">
    <ul :id="`ul${index}`">
      <li v-for="(d,i) in item.data" :key="i" @click="checkItem(d,index)" :class="ids[index]&&ids[index].indexOf(d.id)!==-1?'cur':''">
        {{d.shortName}}
        <i class="iconfont jiantou" v-if="d.childrenType!=='00'&&d.children && d.children.length>0"></i>
      </li>
    </ul>
  </van-tab>
</van-tabs>

script

data () {
    return {
      areaName: '',
      flattedOrgTree: [],    //扁平化处理后的机构数组
      areas: [],     // 树型机构
      areaId: '',   // 机构id  
      list: [],   // 联动框内容数组
      active: 0,
      maxLevel: 1,
      ids: [], // 选择机构的id组
      arr: [], // 反向渲染暂存的id组
      scrollTops: [] // scrollTop组
    }
  },

初始化

this.$nextTick(() => {
  this.list[0] = {
    data: this.areas,
    title: this.areas[0].name,
    id: this.areas[0].id
  }
  this.ids[0] = this.areas[0].id
  this.$forceUpdate()
})

点击展示下级

checkItem (item, n) {
  if (item.children && item.children.length > 0) {
    this.list.splice(n + 1)
    this.list[n].title = item.name
    this.list[n].id = item.id
    this.list = [...this.list, {
      data: item.children,
      title: '请选择',
      id: ''
    }]
    this.ids[n] = item.children[0].id
    setTimeout(() => {
      this.active = n + 1
    }, 10)
  } else {
  	// 点击最后一级 
  	this.ids[n] = item.id
  	this.areaId = item.id
  }
},

通过 areaId 反向渲染联动框

// 反查父集id链
reList (id) {
  if (id !== '0') {
    this.arr.unshift(id)
  }
  if (this.flattedOrgTree[id] && this.flattedOrgTree[id].parentId && this.flattedOrgTree[this.flattedOrgTree[id].parentId]) {
    this.reList(obj, this.flattedOrgTree[id].parentId)
  }
},
initPicker () {
  this.list[0] = {
     data: this.areas,
     title: this.areas[0].name,
     id: this.areas[0].id
   }
   this.ids[0] = this.areas[0].id
   this.arr = []
   this.reList(this.areaId)
   if (//areaId不是初级id) {
     this.ids = this.arr
     if (this.ids.length > 0) {
       for (let i = 1; i < this.ids.length; i++) {
         const pid = this.flattedOrgTree[this.ids[i]].parentId
         const p = this.flattedOrgTree[pid]
         let data = [{ ...p, children: [] }, ...p.children]
         const format = function (arr) {
           if (arr.length < 1) return
           arr.forEach(obj => {
             if (obj.children && obj.children.length > 0) {
               const hasUnshiftArr = obj.children.filter(d => { return d.id === obj.id })
               if (hasUnshiftArr.length === 0) {
                 obj.children.unshift({
                   ...obj,
                   children: []
                 })
               }
               format(obj.children)
             }
           })
         }
         format(data)
         data = data.map(i => {
           if (i.childrenType === '00') {
             return {
               ...i,
               children: []
             }
           } else {
             return i
           }
         })
         this.list[i] = {
           data: data,
           title: this.flattedOrgTree[this.ids[i]].name,
           id: this.flattedOrgTree[this.ids[i]].id
         }
       }
       this.active = this.ids.length - 1
     }
   }
 },

通过active获取当前选中标签 控制其居中显示 项目使用了rem item行高设置为0.4rem 反向需计算

watch: {
    active (n) {
      if (this.list[n] && this.list[n].data && this.list[n].data.length > 0) {
        let curIndex = 0
        this.list[n].data.forEach((item, index) => {
          if (item.id === this.ids[n]) {
            curIndex = index
          }
        })
        this.$nextTick(() => {
          const screenWidth = document.body.clientWidth
          document.getElementById(`ul${n}`).scrollTop = curIndex * 0.4 * screenWidth * 100 / 750
        })
      }
    }
   }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值