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. 注意事项

  • 大数据量时考虑虚拟滚动
  • 移动端注意触摸体验
  • 提供全选/反选功能(如需要)

这种方式可以灵活实现多选联级选择,根据实际需求调整样式和功能。

回到顶部