Thursday, November 26, 2020

uniapp自定义picker城市多级联动组件

uniapp自定义picker城市多级联动组件

  • 支持多端——h5、app、微信小程序、支付宝小程序...
  • 支持自定义配置picker插件级数
  • 支持无限级

注意事项:插件传入数据格式为children树形格式,内部包含:id、name

参数类型描述默认值必选
titlestring标题''
layernumber控制几级联动1
dataarr数据 如:[{text: '', adcode: '', children: [{text: '', adcode: ''}]}][]

组件运行图示:
2

组件选择后返回数据如:
console

引用示例:

<template>	<view >		<view :>				<view @click.stop="showPicker($event)">picker无限级联动</view>			</view>		<aui-picker 			ref="picker" 			:title="auiPicker.title"			:layer="auiPicker.layer"			:data="auiPicker.data"			@callback="pickerCallback"		></aui-picker>	</view></template><script>	import auiPicker from '@/components/aui-picker/aui-picker.vue';	export default {		components: {			auiPicker		},		data() {			return {				auiPicker: {					title: 'picker多级联动',					layer: null,					data: []				},			}		},		created(){					},		mounted() {					},		methods: {			//显示picker多级联动弹窗			showPicker(e){				const _this = this;				_this.auiPicker.data=[{					id: "1001",					name: "一级菜单1",					children: [{						id: "1002",						name: "二级菜单1-1",						children: [{							id: "1003",							name: "三级菜单1-1",							children: [{								id: "1004",								name: "四级菜单1-1"							}]						}]					}]				},				{					id: "1005",					name: "一级菜单2",					children: [{						id: "1006",						name: "二级菜单2-1",						children: [{							id: "1007",							name: "三级菜单2-1",							children: [{								id: "1008",								name: "四级菜单2-1"							}]						}]					}]				}];				_this.$refs.picker.open().then(function(){					console.log('picker打开');				});			},			//picker多级联动回调			pickerCallback(e){				const _this = this;				console.log(e);				let result = '';				e.data.forEach(function(item, index){					result += item.name + ' ';				});				uni.showModal({				 title: '提示',				 content: result,				 success: function (res) {				  if (res.confirm) {				   console.log('用户点击确定');				  } else if (res.cancel) {				   console.log('用户点击取消');				  }				 }				});			}		}	}</script><style>	.aui-content{padding: 15px 0 0 0;}</style>

aui-picker组件完整代码:

项目components文件夹下创建aui-picker夹,此文件夹下创建aui-picker.vue——多级联动组件

<template name="aui-picker">	<view v-if="SHOW" :	>		<view @click.stop="close"></view>		<view >	  <view >	   <view v-if="title">{{title}}</view>	   <view @click.stop="close"></view>	  </view>	  <view >				<view 					v-if="nav.length>0"					v-for="(item, index) in nav" 					:key="index" 					:data-index="index" 					: 					:					@click.stop="_changeNav($event)"				>{{item.name}}</view>								<view 														:key="nav.length" 					:data-index="nav.length"					: 					:					@click.stop="_changeNav($event)"				>请选择</view>				<view :></view>			</view>	  <view >	   <view >					<view 						v-for="(list, index) in queryItems.length + 1"						:key="index" 						:data-index="index" 						:					>						<view v-if="index == 0">							<view 								v-for="(item, key) in items" 								v-if="item.pid=='0'"								:key="key"								:data-pindex="index"								:data-index="key"								:data-id="item.id" 								:data-pid="item.pid"								:data-name="item.name"								:								:								@click.stop="_chooseItem($event)"								@touchstart="_btnTouchStart($event)"								@touchmove="_btnTouchEnd($event)"								@touchend="_btnTouchEnd($event)"							>{{item.name}}</view>						</view>						<view v-else>							<view 								v-for="(item, key) in queryItems[index-1]"								:key="key"								:data-pindex="index"								:data-index="key"								:data-id="item.id"								:data-pid="item.pid"								:data-name="item.name"								:								:								@click.stop="_chooseItem($event)"								@touchstart="_btnTouchStart($event)"								@touchmove="_btnTouchEnd($event)"								@touchend="_btnTouchEnd($event)"							>{{item.name}}</view>						</view>					</view>				</view>	  </view>		</view>	</view></template><script>	export default {		name: 'aui-picker',		props: {			title: { //标题				type: String,				default: ''			},			layer: { //控制几级联动,默认无限级(跟随数据有无下级)				type: Number,				default: null			},			data: { //数据 如:[{id: '', name: '', children: [{id: '', name: ''}]}]				type: Array,				default (){					return [						// [{id: '', name: '', children: [{id: '', name: ''}]}]					]				}			}		},		data(){			return {				SHOW: false,				FADE: -1,				nav: [],				items: [],				queryItems: [],				navCurrentIndex: 0,				navBorderLeft: 40,				result: [],				touchConfig: {					index: -1,					pindex: -1,					style: {						color: '#197DE0',						background: '#EFEFEF'					} 				}			}		},		created(){			const _this = this;		},		watch:{			data(){				const _this = this;				const data = _this.data;				_this.items = _this._flatten(data, '0')	    }  	  },		mounted(){					},		methods:{			// 打开			open(){				const _this = this;								_this.reset(); //打开时重置picker				return new Promise(function(resolve, reject){					_this.SHOW = true;					_this.FADE = 1;					resolve();				});			},			// 关闭			close(){				const _this = this;				return new Promise(function(resolve, reject){					_this.FADE = 0;					const _hidetimer = setTimeout(()=>{						_this.SHOW = false;						_this.FADE = -1;						clearTimeout(_hidetimer);						resolve();											},100)					});			},			//重置			reset(){				const _this = this;				_this.queryItems = [];				_this.nav = [];				_this.navBorderLeft = 40;				_this.navCurrentIndex = 0;				_this.result = [];			},			//导航栏切换			_changeNav(e){				const _this = this;				const index = Number(e.currentTarget.dataset.index);				_this.navCurrentIndex = index;				const _el = uni.createSelectorQuery().in(this).select(".aui-picker-navitem-"+index);				_el.boundingClientRect(data => {					_this.navBorderLeft = data.left + 20;				}).exec();			},			//数据选择			_chooseItem(e){				const _this = this;				const id = e.currentTarget.dataset.id;				const name = e.currentTarget.dataset.name;				const pid = e.currentTarget.dataset.pid;				const _arr = [];				_this.result[_this.navCurrentIndex] = {id: id, name: name, pid: pid};				if(					(!_this._isDefine(_this.layer) && _this._isDefine(_this._deepQuery(_this.data, id).children)) 					|| 					(_this.navCurrentIndex < (Number(_this.layer) - 1) && _this._isDefine(_this._deepQuery(_this.data, id).children))				)				{ //有下级数据					_this._deepQuery(_this.data, id).children.forEach(function(item, index){						_arr.push({id: item.id, name: item.name, pid: id});					});					if(_this.navCurrentIndex == _this.queryItems.length)					{ //选择数据						_this.queryItems.push(_arr);						_this.nav.push({name: name});					}					else					{ //重新选择数据						_this.queryItems.splice(_this.navCurrentIndex+1, 1);						_this.nav.splice(_this.navCurrentIndex+1, 1);						_this.queryItems.splice(_this.navCurrentIndex, 1, _arr);						_this.nav.splice(_this.navCurrentIndex, 1, {name: name});					}					_this.navCurrentIndex = _this.navCurrentIndex + 1;					const _el = uni.createSelectorQuery().in(this).select(".aui-picker-navitem-"+_this.navCurrentIndex);					setTimeout(()=>{						_el.boundingClientRect(data => {							_this.navBorderLeft = data.left + 20;						}).exec();					},100)				}				else				{ //无下级数据					_this.close().then(()=>{						_this.$emit("callback", {status: 0, data: _this.result});					});				}			},						//递归遍历——将树形结构数据转化为数组格式			_flatten(tree, pid) {				return tree.reduce((arr, {id, name, children = []}) =>				arr.concat([{id, name, pid}], this._flatten(children, id)), [])			},			//根据id查询对应的数据(如查询id=10100对应的对象)			_deepQuery(tree, id) {			 let isGet = false;			 let retNode = null;			 function deepSearch(tree, id){			  for(let i = 0; i < tree.length; i++) {			   if(tree[i].children && tree[i].children.length > 0) {			    deepSearch(tree[i].children, id);			   }			   if(id === tree[i].id || isGet) {			    isGet||(retNode = tree[i]);			    isGet = true;			    break;			   }			  }			 }			 deepSearch(tree, id);			 return retNode;			},			/***判断字符串是否为空			 @param {string} str 变量			 @example: aui.isDefine("变量");			*/			_isDefine(str){				if (str==null || str=="" || str=="undefined" || str==undefined || str=="null" || str=="(null)" || str=='NULL' || typeof (str)=='undefined'){					return false;				}else{					str = str + "";					str = str.replace(/\s/g, "");					if (str == ""){return false;}					return true;				}			},			_btnTouchStart(e){				const _this = this,					index = Number(e.currentTarget.dataset.index),					pindex = Number(e.currentTarget.dataset.pindex);				_this.touchConfig.index = index;				_this.touchConfig.pindex = pindex;			},			_btnTouchEnd(e){				const _this = this,					index = Number(e.currentTarget.dataset.index),					pindex = Number(e.currentTarget.dataset.pindex);				_this.touchConfig.index = -1;				_this.touchConfig.pindex = -1;			},			}	}</script><style scoped>	/* ====================		多级联动弹窗	 =====================*/	.aui-picker{		width: 100vw;		height: 100vh;		opacity: 0;				position: fixed;		top: 0;		left: 0;		z-index: 999;		/* display: none; */	}	.aui-picker.aui-picker-in{		-moz-animation: aui-fade-in .1s ease-out forwards;		-ms-animation: aui-fade-in .1s ease-out forwards;		-webkit-animation: aui-fade-in .1s ease-out forwards;		animation: aui-fade-in .1s ease-out forwards;	}	.aui-picker.aui-picker-out{		-moz-animation: aui-fade-out .1s ease-out forwards;		-ms-animation: aui-fade-out .1s ease-out forwards;		-webkit-animation: aui-fade-out .1s ease-out forwards;		animation: aui-fade-out .1s ease-out forwards;	}	.aui-picker-main{		width: 100vw;		height: 50vh;		background: #FFF;		border-radius: 15px 15px 0 0;		position: absolute;		left: 0px;		bottom: -50vh;				z-index: 999;	}	.aui-picker.aui-picker-in .aui-picker-main{		-moz-animation: aui-slide-up-screen .2s ease-out forwards;		-ms-animation: aui-slide-up-screen .2s ease-out forwards;		-webkit-animation: aui-slide-up-screen .2s ease-out forwards;		animation: aui-slide-up-screen .2s ease-out forwards;	}	.aui-picker.aui-picker-out .aui-picker-main{		-moz-animation: aui-slide-down-screen .2s ease-out forwards;		-ms-animation: aui-slide-down-screen .2s ease-out forwards;		-webkit-animation: aui-slide-down-screen .2s ease-out forwards;		animation: aui-slide-down-screen .2s ease-out forwards;	}	.aui-picker-header{		width: 100%;		min-height: 50px;		position: relative;		z-index: 999;		background: #F2F2F2;		border-radius: 15px 15px 0 0;	}	.aui-picker-header::after{		content: '';		width: 100%;		height: 1px;		background: rgba(100,100,100,.3);		-moz-transform: scaleY(.3);		-ms-transform: scaleY(.3);		-webkit-transform: scaleY(.3);		transform: scaleY(.3);		position: absolute;		left: 0;		bottom: 0;		z-index: 999;	}	.aui-picker-title{		line-height: 20px;		text-align: center;		font-size: 17px;		color: #333;		padding: 15px;		box-sizing: border-box;		position: absolute;		left: 50px;		right: 50px;		top: 0;	}	.aui-picker-close.iconfont{		width: 50px;		height: 50px;		line-height: 50px;		text-align: center;		font-size: 20px;		color: #aaa;		border-radius: 0 10px 0 0;		position: absolute;		right: 0;		top: 0;	}	.aui-picker-content{		width: 100%;		height: -webkit-calc(100% - 100px);		height: calc(100% - 100px);	}	.aui-picker-nav{		width: 100%;		height: 50px;		text-align: left;		padding: 0 20px;		margin: 0 0 1px 0;		justify-content: flex-start;		white-space: nowrap;		box-sizing: border-box;		position: relative;	}	.aui-picker-nav::after{		content: '';		width: 100%;		height: 1px;		background: rgba(100,100,100,.3);		-moz-transform: scaleY(.3);		-ms-transform: scaleY(.3);		-webkit-transform: scaleY(.3);		transform: scaleY(.3);		position: absolute;		left: 0;		bottom: 0;		z-index: 999;	}	.aui-picker-navitem{		width: 80px;		line-height: 50px;		font-size: 16px;		margin: 0 30px 0 0;		text-align: center;		display: inline-block;		overflow: hidden;		white-space: nowrap;		text-overflow: ellipsis;	}	.aui-picker-navitem.active{		color: #197DE0;	}	.aui-picker-navborder{		width: 40px;		height: 3px;		background: #197DE0;		border-radius: 5px;		transition: left .15s;		position: absolute;		left: 40px;		bottom: 0;	}	.aui-picker-lists{		width: 100%;		height: 100%;		justify-content: space-around;		white-space: nowrap;	}	.aui-picker-list{		width: 100%;		height: 100%;		overflow: hidden;		overflow-y: scroll;		display: none;		vertical-align: top;	}	.aui-picker-list.active{		display: inline-block;	}	.aui-picker-list-warp{		width: 100%;		height: auto;		box-sizing: border-box;		padding: 15px 0;		display: inline-block;	}	.aui-picker-item{		width: 100%;		height: 50px;		line-height: 50px;		padding: 0 15px;		box-sizing: border-box;		font-size: 15px;		color: #333;		position: relative;	}	.aui-picker-item.active{		color: #197DE0;	}	.aui-picker-item.active::after{		content: '✔';		font-size: 15px;		color: #197DE0;		position: absolute;		top: 0px;		right: 10px;	}</style>








原文转载:http://www.shaoqun.com/a/493244.html

海拍客:https://www.ikjzd.com/w/1742

活动树:https://www.ikjzd.com/w/1518

naning9韩国官网:https://www.ikjzd.com/w/2401


uniapp自定义picker城市多级联动组件支持多端——h5、app、微信小程序、支付宝小程序...支持自定义配置picker插件级数支持无限级注意事项:插件传入数据格式为children树形格式,内部包含:id、name参数类型描述默认值必选titlestring标题''否layernumber控制几级联动1否dataarr数据如:[{text:'',adcod
自贸区跨境通网站:自贸区跨境通网站
垂直电商:垂直电商
广州旅游线路推荐一下?:广州旅游线路推荐一下?
亚马逊各站点DOTD/BD提报攻略及申请资料汇总!:亚马逊各站点DOTD/BD提报攻略及申请资料汇总!
花卉小镇几点开门?清远花卉小镇开门时间?:花卉小镇几点开门?清远花卉小镇开门时间?

No comments:

Post a Comment