# tui-picker 联动选择 开源组件

介绍

联动选择,可自行调整联动级数,示例为三级联动。

完整的全国省市区数据下载 city-data (opens new window)

# picker组件联动

picker 组件的具体使用请参考 官方文档 (opens new window)

设置mode = multiSelector,多列选择器。

change 事件:value 改变时触发 change 事件,event.detail = {value: value}

columnchange 事件:某一列的值改变时触发 columnchange 事件,event.detail = {column: column, value: value},column 的值表示改变了第几列(下标从0开始),value 的值表示变更值的下标

    <template>
     <view class="container">
     	<picker :value="value" mode="multiSelector" @change="picker" @columnchange="columnPicker" :range="multiArray">
     		<tui-button  shape="circle">请选择</tui-button>
     	</picker>
     	<view class="result">
     		{{text}}
     	</view>
     </view>
    </template>
    
    <script>
      //数据请看介绍获取,或拷贝示例中的js文件
     import cityData from '@/utils/picker.city.js'
     export default {
     	data() {
     		return {
     			selectList: cityData, //接口返回picker数据,此处就直接使用本地测试数据
     			multiArray: [], //picker数据
     			value: [0, 0, 0],
     			text: "",
     			id: ""
     		}
     	},
     	onLoad: function() {
     		this.multiArray = [
     			this.toArr(this.selectList),
     			this.toArr(this.selectList[0].children),
     			this.toArr(this.selectList[0].children[0].children)
     		]
     	},
     	methods: {
     		picker: function(e) {
     			let value = e.detail.value;
     			if (this.selectList.length > 0) {
     				let provice = this.selectList[value[0]].text
     				let city = this.selectList[value[0]].children[value[1]].text
     				let district = this.selectList[value[0]].children[value[1]].children[value[2]].text
     				this.text = provice + " " + city + " " + district;
     				this.id = this.selectList[value[0]].children[value[1]].children[value[2]].value
     			}
     		},
     		toArr(object) {
     			let arr = [];
     			for (let i in object) {
     				arr.push(object[i].text);
     			}
     			return arr;
     		},
     		columnPicker: function(e) {
     			//第几列 下标从0开始
     			let column = e.detail.column;
     			//第几行 下标从0开始
     			let value = e.detail.value;
     			if (column === 0) {
     				this.multiArray = [
     					this.multiArray[0],
     					this.toArr(this.selectList[value].children),
     					this.toArr(this.selectList[value].children[0].children)
     				];
     				this.value = [value, 0, 0]
     			} else if (column === 1) {
     				this.multiArray = [
     					this.multiArray[0],
     					this.multiArray[1],
     					this.toArr(this.selectList[this.value[0]].children[value].children)
     				];
     				this.value = [this.value[0], value, 0]
     			}
     		}
     	}
     }
    </script>
    
    <style>
     .container {
     	padding: 100rpx 30rpx
     }
    
     .result {
     	padding: 60rpx 20rpx;
     	font-size: 30rpx;
     	color: #333
     }
    
    </style>
    
    <view class="container">
     <picker value="{{value}}" mode="multiSelector" bindchange="picker" bindcolumnchange="columnPicker" range="{{multiArray}}">
     	<tui-button  shape="circle">请选择</tui-button>
     </picker>
     <view class="result">
     	{{text}}
     </view>
    </view>
    
    //数据请看介绍获取,或拷贝示例中的js文件
    const cityData = require('../../../utils/picker.city.js')
    Page({
    data: {
      selectList: cityData, //接口返回picker数据,此处就直接使用本地测试数据
      multiArray: [], //picker数据
      value: [0, 0, 0],
      text: "",
      id: ""
    },
    onLoad: function (options) {
      let multiArray = [
        this.toArr(this.data.selectList),
        this.toArr(this.data.selectList[0].children),
        this.toArr(this.data.selectList[0].children[0].children)
      ]
      this.setData({
        multiArray: multiArray
      })
    },
    picker: function (e) {
      let value = e.detail.value;
      if (this.data.selectList.length > 0) {
        let provice = this.data.selectList[value[0]].text
        let city = this.data.selectList[value[0]].children[value[1]].text
        let district = this.data.selectList[value[0]].children[value[1]].children[value[2]].text
        this.setData({
          text:provice + " " + city + " " + district,
          id:this.data.selectList[value[0]].children[value[1]].children[value[2]].value
        })
      }
    },
    toArr(object) {
      let arr = [];
      for (let i in object) {
        arr.push(object[i].text);
      }
      return arr;
    },
    columnPicker: function (e) {
      //第几列 下标从0开始
      let column = e.detail.column;
      //第几行 下标从0开始
      let value = e.detail.value;
      if (column === 0) {
        let multiArray = [
          this.data.multiArray[0],
          this.toArr(this.data.selectList[value].children),
          this.toArr(this.data.selectList[value].children[0].children)
        ];
        this.setData({
          multiArray:multiArray,
          value:[value, 0, 0]
        })
      } else if (column === 1) {
        let multiArray = [
          this.data.multiArray[0],
          this.data.multiArray[1],
          this.toArr(this.data.selectList[this.data.value[0]].children[value].children)
        ];
        this.setData({
          multiArray:multiArray,
          value:[this.data.value[0], value, 0]
        })
      }
     }
    })
    
    .container {
      padding: 100rpx 30rpx
    }
    
    .result {
      padding: 60rpx 20rpx;
      font-size: 30rpx;
      color: #333
    }
    
    // Make sure to add code blocks to your code group

    约定好数据格式,联动逻辑实现主要根据事件触发进行相关数据处理。

    # picker-view组件联动

    picker-view 组件的具体使用请参考 官方文档 (opens new window)

    change 事件:当滚动选择,value 改变时触发 change 事件,event.detail = {value: value};value为数组,表示 picker-view 内的 picker-view-column 当前选择的是第几项(下标从 0 开始)

      <template>
       <view class="conatiner">
       	<view class="btn-select">
       		<tui-button shape="circle" @click="showPicker">请选择</tui-button>
       	</view>
      
       	<!--picker-view start-->
       	<view class="tui-mask-screen" :class="[showPickerStatus?'tui-mask-show':'']" @tap="hidePicker"></view>
       	<view class="tui-picker-box" :class="[showPickerStatus?'tui-pickerbox-show':'']">
       		<view class="picker-header tui-list-item">
       			<view class="btn-cancle" hover-class="tui-opcity" :hover-stay-time="150" @tap.stop="hidePicker">取消</view>
       			<view class="btn-sure" hover-class="tui-opcity" :hover-stay-time="150" @tap.stop="picker">确定</view>
       		</view>
       		<picker-view indicator-style="height: 50px;" class="picker-view" :value="value" @change="columnPicker">
       			<picker-view-column>
       				<view v-for="(item,index) in proviceArr" :key="index" class="item">{{item}}</view>
       			</picker-view-column>
       			<picker-view-column>
       				<view v-for="(item,index) in cityArr" :key="index" class="item">{{item}}</view>
       			</picker-view-column>
       			<picker-view-column>
       				<view v-for="(item,index) in districtArr" :key="index" class="item">{{item}}</view>
       			</picker-view-column>
       		</picker-view>
       	</view>
       	<!--picker-view end-->
       </view>
      </template>
      
      <script>
       import cityData from '@/utils/picker.city.js'
       export default {
       	data() {
       		return {
       			proviceArr: [],
       			cityArr: [],
       			districtArr: [],
       			value: [0, 0, 0],
       			iconHidden: true,
       			showPickerStatus: false,
       			text: ["请选择", "请选择", "请选择"]
       		}
       	},
       	onLoad: function() {
       		//初始化数据
       		this.proviceArr = this.toArr(cityData);
       		this.cityArr = this.toArr(cityData[0].children);
       		this.districtArr = this.toArr(cityData[0].children[0].children)
       	},
       	methods: {
       		toArr(object) {
       			let arr = [];
       			for (let i in object) {
       				arr.push(object[i].text);
       			}
       			return arr;
       		},
       		//picker change切换事件
       		columnPicker: function(e) {
       			let value = e.detail.value;
       			//如果两者下标不一致,表示滚动过
       			if (this.value[0] !== value[0]) {
       				this.proviceArr = this.proviceArr;
       				this.cityArr = this.toArr(cityData[value[0]].children);
       				this.districtArr = this.toArr(cityData[value[0]].children[0].children);
       				this.value = [value[0], 0, 0]
       			} else if (this.value[1] !== value[1]) {
       				this.proviceArr = this.proviceArr;
       				this.cityArr = this.cityArr;
       				this.districtArr = this.toArr(cityData[value[0]].children[value[1]].children);
       				this.value = [value[0], value[1], 0]
       			} else {
       				this.value = value
       			}
       		},
       		//确定按钮
       		picker: function(e) {
       			let value = this.value;
       			if (cityData.length > 0) {
       				let provice = cityData[value[0]].text;
       				let city = cityData[value[0]].children[value[1]].text;
       				let district = cityData[value[0]].children[value[1]].children[value[2]].text;
       				this.text = [provice, city, district];
       				this.showPickerStatus = false
       			}
       		},
       		// 显示picker-view
       		showPicker: function() {
       			this.showPickerStatus = true
       		},
       		// 隐藏picker-view
       		hidePicker: function() {
       			this.showPickerStatus = false
       		}
       	}
       }
      </script>
      
      <style>
       /* picker start*/
      
       .tui-mask-screen {
       	position: fixed;
       	top: 0;
       	left: 0;
       	right: 0;
       	bottom: 0;
       	background: rgba(0, 0, 0, 0.6);
       	z-index: 99996;
       	transition: all 0.3s ease-in-out;
       	opacity: 0;
       	visibility: hidden;
       }
      
       .tui-mask-show {
       	opacity: 1;
       	visibility: visible;
       }
      
       .tui-picker-box {
       	width: 100%;
       	position: fixed;
       	left: 0;
       	right: 0;
       	bottom: 0;
       	z-index: 99999;
       	visibility: hidden;
       	transform: translate3d(0, 100%, 0);
       	transform-origin: center;
       	transition: all 0.3s ease-in-out;
       	min-height: 20rpx;
       	background: #fff;
       }
      
       .tui-pickerbox-show {
       	transform: translate3d(0, 0, 0);
       	visibility: visible;
       }
      
       .picker-header {
       	width: 100%;
       	height: 90rpx;
       	padding: 0 46rpx;
       	display: flex;
       	justify-content: space-between;
       	align-items: center;
       	box-sizing: border-box;
       	font-size: 32rpx;
       	background: #fff;
       }
      
       .tui-list-item::after {
       	left: 0;
       }
      
       .btn-cancle {
       	padding: 20rpx;
       	color: #888;
       }
      
       .btn-sure {
       	padding: 20rpx;
       	color: #5677fc;
       }
      
       .picker-view {
       	width: 100%;
       	height: 260px;
       }
      
       .item {
       	line-height: 50px;
       	text-align: center;
       }
      
       /* picker end*/
      
       .btn-select {
       	width: 100%;
       	padding: 20rpx 40rpx;
       	box-sizing: border-box;
       }
      </style>
      
      <!--微信小程序-->
      <view class="conatiner">
       <view class="btn-select">
       	<tui-button shape="circle" bindclick="showPicker">请选择</tui-button>
       </view>
      
       <!--picker-view start-->
       <view class="tui-mask-screen {{showPickerStatus?'tui-mask-show':''}}" bindtap="hidePicker"></view>
       <view class="tui-picker-box {{showPickerStatus?'tui-pickerbox-show':''}}">
       	<view class="picker-header tui-list-item">
       		<view class="btn-cancle" hover-class="tui-opcity" hover-stay-time="150" catchtap="hidePicker">取消</view>
       		<view class="btn-sure" hover-class="tui-opcity" hover-stay-time="150" catchtap="picker">确定</view>
       	</view>
       	<picker-view indicator-style="height: 50px;" class="picker-view" value="{{value}}" bindchange="columnPicker">
       		<picker-view-column>
       			<view wx:for="{{proviceArr}}" wx:key="index" class="item">{{item}}</view>
       		</picker-view-column>
       		<picker-view-column>
       			<view wx:for="{{cityArr}}" wx:key="index" class="item">{{item}}</view>
       		</picker-view-column>
       		<picker-view-column>
       			<view wx:for="{{districtArr}}" wx:key="index" class="item">{{item}}</view>
       		</picker-view-column>
       	</picker-view>
       </view>
       <!--picker-view end-->
      </view>
      
      // data 数据 及 方法
      const cityData = require('../../../utils/picker.city.js')
      Page({
       data: {
         proviceArr: [],
         cityArr: [],
         districtArr: [],
         value: [0, 0, 0],
         iconHidden: true,
         showPickerStatus: false,
         text: ["请选择", "请选择", "请选择"]
       },
       onLoad: function (options) {
         //初始化数据
         this.setData({
           proviceArr: this.toArr(cityData),
           cityArr: this.toArr(cityData[0].children),
           districtArr: this.toArr(cityData[0].children[0].children)
         })
       },
       toArr(object) {
         let arr = [];
         for (let i in object) {
           arr.push(object[i].text);
         }
         return arr;
       },
       //picker change切换事件
       columnPicker: function (e) {
         let value = e.detail.value;
         //如果两者下标不一致,表示滚动过
         if (this.data.value[0] !== value[0]) {
           this.setData({
             proviceArr: this.data.proviceArr,
             cityArr: this.toArr(cityData[value[0]].children),
             districtArr: this.toArr(cityData[value[0]].children[0].children),
             value: [value[0], 0, 0]
           })
         } else if (this.data.value[1] !== value[1]) {
           this.setData({
             proviceArr: this.data.proviceArr,
             cityArr: this.data.cityArr,
             districtArr: this.toArr(cityData[value[0]].children[value[1]].children),
             value: [value[0], value[1], 0]
           })
         } else {
           this.setData({
             value: value
           })
         }
       },
       //确定按钮
       picker: function (e) {
         let value = this.data.value;
         if (cityData.length > 0) {
           let provice = cityData[value[0]].text;
           let city = cityData[value[0]].children[value[1]].text;
           let district = cityData[value[0]].children[value[1]].children[value[2]].text;
           this.setData({
             text: [provice, city, district],
             showPickerStatus: false
           })
         }
       },
       // 显示picker-view
       showPicker: function () {
         this.setData({
           showPickerStatus: true
         })
       },
       // 隐藏picker-view
       hidePicker: function () {
         this.setData({
           showPickerStatus: false
         })
       }
      })
      
      /* picker start*/
      
      .tui-mask-screen {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: rgba(0, 0, 0, 0.6);
        z-index: 99996;
        transition: all 0.3s ease-in-out;
        opacity: 0;
        visibility: hidden;
      }
      
      .tui-mask-show {
        opacity: 1;
        visibility: visible;
      }
      
      .tui-picker-box {
        width: 100%;
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 99999;
        visibility: hidden;
        transform: translate3d(0, 100%, 0);
        transform-origin: center;
        transition: all 0.3s ease-in-out;
        min-height: 20rpx;
        background: #fff;
      }
      
      .tui-pickerbox-show {
        transform: translate3d(0, 0, 0);
        visibility: visible;
      }
      
      .picker-header {
        width: 100%;
        height: 90rpx;
        padding: 0 46rpx;
        display: flex;
        justify-content: space-between;
        align-items: center;
        box-sizing: border-box;
        font-size: 32rpx;
        background: #fff;
      }
      
      .tui-list-item::after {
        left: 0;
      }
      
      .btn-cancle {
        padding: 20rpx;
        color: #888;
      }
      
      .btn-sure {
        padding: 20rpx;
        color: #5677fc;
      }
      
      .picker-view {
        width: 100%;
        height: 260px;
      }
      
      .item {
        line-height: 50px;
        text-align: center;
      }
      
      /* picker end*/
      
      .btn-select {
      	width: 100%;
      	padding: 20rpx 40rpx;
      	box-sizing: border-box;
      }
      
      // Make sure to add code blocks to your code group

      约定好数据格式,联动逻辑实现主要根据事件触发进行相关数据处理。

      TIP

      此内容为官方组件示例,建议使用ThorUI 封装组件 tui-picker

      # 预览

      完整的全国省市区数据下载 city-data (opens new window)

      # 特别说明

      • 该组件为 开源组件,uni-app版所有用户均可免费使用。
      • 微信小程序原生版仅开源至v1.4.2,后续版本需开通会员才可获取使用。

      # 线上程序扫码预览

      ThorUI组件库 H5二维码 ThorUI示例
      ThorUI组件库小程序码 H5二维码 ThorUI示例小程序码
      Last Updated: 7/21/2023, 2:12:46 PM