uniapp 多选联级选择如何实现
在uniapp中如何实现多级联动的多选功能?比如省市区的三级联动选择,要求可以多选,并且选中的项能正确返回层级关系。看了官方picker组件似乎只支持单列选择,有没有现成的插件或比较优雅的实现方案?最好能支持动态加载数据。
        
          2 回复
        
      
      
        使用 uni-data-picker 组件,设置 multiple 属性为 true 即可实现多选联级选择。需配合云端数据库或本地数据源,配置级联字段如 parent_id 等。
在 UniApp 中实现多选联级选择(例如省市区选择),可以通过以下步骤实现:
1. 使用 picker 组件 + 自定义多选逻辑
UniApp 的 picker 组件默认不支持多选,但可以通过自定义数据绑定和界面实现多选效果。
示例代码:
<template>
  <view>
    <!-- 触发选择的按钮 -->
    <button @click="showPicker = true">选择地区</button>
    <!-- 自定义多选联级选择器 -->
    <view v-if="showPicker" class="picker-modal">
      <!-- 级联选择区域 -->
      <view class="picker-header">
        <text @click="cancelPicker">取消</text>
        <text @click="confirmPicker">确定</text>
      </view>
      <view class="picker-body">
        <!-- 第一级 -->
        <scroll-view scroll-y class="picker-column">
          <view 
            v-for="item in provinceList" 
            :key="item.id"
            :class="['picker-item', selectedProvince?.id === item.id ? 'active' : '']"
            @click="selectProvince(item)"
          >
            {{ item.name }}
          </view>
        </scroll-view>
        <!-- 第二级 -->
        <scroll-view scroll-y class="picker-column" v-if="cityList.length">
          <view 
            v-for="item in cityList" 
            :key="item.id"
            :class="['picker-item', selectedCity?.id === item.id ? 'active' : '']"
            @click="selectCity(item)"
          >
            {{ item.name }}
          </view>
        </scroll-view>
        <!-- 第三级 -->
        <scroll-view scroll-y class="picker-column" v-if="districtList.length">
          <view 
            v-for="item in districtList" 
            :key="item.id"
            :class="['picker-item', isSelectedDistrict(item) ? 'active' : '']"
            @click="toggleDistrict(item)"
          >
            {{ item.name }}
          </view>
        </scroll-view>
      </view>
    </view>
    <!-- 显示已选区域 -->
    <view>
      <text>已选择:{{ selectedDistricts.map(d => d.name).join(', ') }}</text>
    </view>
  </view>
</template>
<script>
export default {
  data() {
    return {
      showPicker: false,
      provinceList: [],
      cityList: [],
      districtList: [],
      selectedProvince: null,
      selectedCity: null,
      selectedDistricts: [] // 存储多选结果
    }
  },
  mounted() {
    this.loadProvinceData()
  },
  methods: {
    // 加载省份数据
    async loadProvinceData() {
      // 这里替换为实际API或本地数据
      this.provinceList = [
        { id: 1, name: '北京市' },
        { id: 2, name: '上海市' }
      ]
    },
    // 选择省份
    selectProvince(province) {
      this.selectedProvince = province
      this.selectedCity = null
      this.districtList = []
      // 加载城市数据
      this.cityList = [
        { id: 11, name: '北京市', provinceId: 1 },
        { id: 21, name: '上海市', provinceId: 2 }
      ].filter(city => city.provinceId === province.id)
    },
    // 选择城市
    selectCity(city) {
      this.selectedCity = city
      // 加载区县数据
      this.districtList = [
        { id: 111, name: '朝阳区', cityId: 11 },
        { id: 112, name: '海淀区', cityId: 11 },
        { id: 211, name: '黄浦区', cityId: 21 },
        { id: 212, name: '静安区', cityId: 21 }
      ].filter(district => district.cityId === city.id)
    },
    // 切换区县选择状态
    toggleDistrict(district) {
      const index = this.selectedDistricts.findIndex(d => d.id === district.id)
      if (index > -1) {
        this.selectedDistricts.splice(index, 1)
      } else {
        this.selectedDistricts.push(district)
      }
    },
    // 检查区县是否被选中
    isSelectedDistrict(district) {
      return this.selectedDistricts.some(d => d.id === district.id)
    },
    // 取消选择
    cancelPicker() {
      this.showPicker = false
      this.selectedDistricts = []
    },
    // 确认选择
    confirmPicker() {
      this.showPicker = false
      // 这里可以处理确认后的逻辑
      console.log('已选择区域:', this.selectedDistricts)
    }
  }
}
</script>
<style scoped>
.picker-modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0,0,0,0.5);
  z-index: 999;
}
.picker-header {
  display: flex;
  justify-content: space-between;
  padding: 20rpx;
  background: #fff;
}
.picker-body {
  display: flex;
  height: 500rpx;
  background: #fff;
}
.picker-column {
  flex: 1;
  height: 100%;
}
.picker-item {
  padding: 20rpx;
  border-bottom: 1px solid #eee;
}
.picker-item.active {
  background: #007AFF;
  color: #fff;
}
</style>
2. 使用第三方组件
也可以使用现成的第三方组件库:
- uView UI:提供 u-picker组件
- Thor UI:提供多选级联组件
3. 实现要点
- 数据源:需要准备完整的级联数据
- 多选逻辑:在最后一级实现多选功能
- 状态管理:维护各级选中状态和最终选择结果
- UI/UX:提供清晰的选中状态反馈
4. 注意事项
- 大数据量时考虑虚拟滚动
- 移动端注意触摸体验
- 提供全选/反选功能(如需要)
这种方式可以灵活实现多选联级选择,根据实际需求调整样式和功能。
 
        
       
                     
                   
                    

