纯手写实现uView级联选择器的模糊搜索功能(可拓展添加对应级次内容功能)

这两天在写公司小程序项目的时候,需要使用级联选择器,并且要支持模糊和新增功能,然后我就去看了下uview组件库和uni的拓展组件中的级联选择器,功能都非常简,不能满足当前的需求... 接下来我就分享一下我完成该需求整体流程和思路... 

 

 实现功能:

        1. 点击右侧箭头可以对所有级联数据进行选择

        2. 输入框输入内容实现级联数据的模糊搜索,搜索后对筛选的级联数据进行选择

 这里我先粘一下结构代码

// 表单部分
<view class="formitem-left">
	<u--input ref="goodsIpt" placeholder="请选择运输货物" border="surround"
		v-model="pageData.goodsName" @input="goodsInput"></u--input>
</view>
<view @click="chooseGoodsName">
	<u-icon :name="rightIcon" color="#999"></u-icon>
</view>

// 级联选择器
<u-picker ref="goodsNameRef" :show="showGoodsNamePic" :columns="goodsNameCol"                :loading="goodsNameLoading" @confirm="confirmGoodsName" @cancel="cancelGoodsName" @change="changeGoodsName"></u-picker>

处理级联选择器 选择的相关逻辑 (改组件需要自己去处理该逻辑) 

changeGoodsName(e) {
				const {
					columnIndex,
					value,
					values, // values为当前变化列的数组内容
					index,
					// 微信小程序无法将picker实例传出来,只能通过ref操作
					picker = this.$refs.goodsNameRef
				} = e

				console.log(columnIndex, 'columnIndex');
				console.log(value, 'value');
				console.log(values, 'values');
				console.log(index, 'index');

				if (columnIndex === 0) {
					let item = this.seaRchGoodsNameData.find(item => item.name == value[0])
					if (item.children && item.children.length) {
						let colTwo = item.children.map(item => item.name)
						let colThree = []
						if (item.children[0].children && item.children[0].children.length) {
							colThree = item.children[0].children.map(item => item.name)
						}
						picker.setColumnValues(1, colTwo)
						picker.setColumnValues(2, colThree)
					} else {
						picker.setColumnValues(1, [])
						picker.setColumnValues(2, [])
					}
				}

				if (columnIndex === 1) {
					let itemFa = this.seaRchGoodsNameData.find(item => item.name == value[0]).children
					let item = itemFa.find(item => item.name == value[1])
					if (item.children && item.children.length) {
						let colThree = item.children.map(item => item.name)
						picker.setColumnValues(2, colThree)
					} else {
						picker.setColumnValues(2, [])
					}
				}
			}

在watch中对级联选择器显示所需要的数据进行处理 (对每一级数据都进行判断处理)

seaRchGoodsNameData: {
				handler() {
					if (!this.seaRchGoodsNameData.length) return this.goodsNameCol = []
					let idxOne = this.seaRchGoodsNameData.map(item => item.name)
					if (!this.seaRchGoodsNameData[0].children || !this.seaRchGoodsNameData[0].children.length) return this
						.goodsNameCol = [idxOne, [],
							[]
						]
					let idxTwo = this.seaRchGoodsNameData[0].children.map(item => item.name)
					if (!this.seaRchGoodsNameData[0].children[0].children || !this.seaRchGoodsNameData[0].children[0]
						.children.length) return this.goodsNameCol = [idxOne,
						idxTwo, []
					]
					let idxThree = this.seaRchGoodsNameData[0].children[0].children.map(item => item.name)
					return this.goodsNameCol = [idxOne, idxTwo, idxThree]
				},
				deep: true,
				immediate: true
			}

到这里以及可以实现级联选择器的显示了,接下来就是去处理级联数据的模糊搜索...

首先定义下模糊搜索的方法,实现可以对每一级数据的模糊搜索进行不同的处理

goodsNameSearch(text, index) {
				let curText = text.toLowerCase()
				if (index == 1) {
					if (curText) {
						let arr = JSON.parse(JSON.stringify(this.goodsNameData)).filter(item => item.name.toLowerCase()
							.indexOf(curText) !== -1)
						if (arr.length) {
							this.seaRchGoodsNameData = arr
						} else {
							this.seaRchGoodsNameData = []
						}
					} else {
						this.seaRchGoodsNameData = this.goodsNameData
					}
				}
				if (index == 2) {
					if (curText) {
						this.seaRchGoodsNameData.forEach(item => {
							if (item.children) {
								let arr = item.children.filter(item => item.name.toLowerCase().indexOf(curText) !==
									-1)
								if (arr.length) {
									item.children = arr
								} else {
									item.children = []
								}
							}
						})
					}
				}
				if (index == 3) {
					if (curText) {
						this.seaRchGoodsNameData.forEach(itemFa => {
							itemFa.children.forEach(item => {
								if (item.children) {
									let arr = item.children.filter(item => item.name.toLowerCase().indexOf(
											curText) !==
										-1)
									if (arr.length) {
										item.children = arr
									} else {
										item.children = []
									}
								}
							})
						})
					}
				}
			},

上述代码就是模糊搜索方法中所涉及到的所以代码,在这里我没有对代码做优化处理,你们使用的过程中,可自行处理。

接下来,就是对输入的值进行分级次处理,并调用模糊搜索的方法... 

goodsInput(val) {
				let valArr = val.split('')
				let length = valArr.filter(item => item == '/').length
				if (this.goodsTimer) clearTimeout(this.goodsTimer)
				this.goodsTimer = setTimeout(() => {
					if (!val) {
						this.seaRchGoodsNameData = this.goodsNameData
					}
					if (!length && valArr[0] != '/') {
						this.goodsNameSearch(val, 1)
					}
					if (length && valArr[0] == '/') {
						this.seaRchGoodsNameData = []
					}
					if (length == 1 && valArr[0] != '/') {
						const arr = val.split('/')
						const valOne = arr[0]
						const valTwo = arr[1]
						if (!valOne.length) {
							this.seaRchGoodsNameData = []
						}
						if (valOne.length) {
							this.goodsNameSearch(valOne, 1)
						}
						if (valTwo.length && this.seaRchGoodsNameData.length) {
							this.goodsNameSearch(valTwo, 2)
						}
					}
					if (length == 2 && valArr[0] != '/') {
						const arr = val.split('/')
						const valOne = arr[0]
						const valTwo = arr[1]
						const valThr = arr[2]
						if (!valOne.length) {
							this.seaRchGoodsNameData = []
						}
						if (valOne.length) {
							this.goodsNameSearch(valOne, 1)
						}
						if (valTwo.length && this.seaRchGoodsNameData.length) {
							this.goodsNameSearch(valTwo, 2)
						}
						if (valThr.length && this.seaRchGoodsNameData.length) {
							this.goodsNameSearch(valThr, 3)
						}
					}

					this.showGoodsNamePic = true
					this.$refs.goodsIpt.focus = false
					uni.hideKeyboard()
				}, 2200)
			}

到这里已经可以实现数据的模糊搜索了,接下来就是分别对确认和取消选择操作进行相关处理...

首先看下确认操作

confirmGoodsName(val) {
				console.log(val.value, '----');
				console.log(val.value.join('/'), '++++');

				let arr = val.value
				if (arr[1] === undefined) {
					arr.splice(1)
				} else if (arr[2] === undefined) {
					arr.splice(2, 1)
				}
				let colOneIndex = ''
				let colTwoIndex = ''
			    let idArr =	arr.map((item,index) => {
					if(index ==0) {
						let colOneItem = this.seaRchGoodsNameData.find(val => val.name == item)
						colOneIndex = this.seaRchGoodsNameData.findIndex(val => val.name == item)
						return colOneItem.id
					} else if(index == 1) {
						let colTwoItem = this.seaRchGoodsNameData[colOneIndex].children.find(val => val.name == item)
						colTwoIndex = this.seaRchGoodsNameData[colOneIndex].children.findIndex(val => val.name == item)
						return colTwoItem.id
					} else if(index == 2) {
						let colThrItem = this.seaRchGoodsNameData[colOneIndex].children[colTwoIndex].children.find(val => val.name == item)
						return colThrItem.id
					}
				})
				this.pageData.goodsName = arr.join('/')
				this.pageData.goodsNameArr = arr
				this.pageData.goodsNameId = idArr
				this.showGoodsNamePic = false
			}

通过级联选择器所得到的名称数据,得到其对应的id数组,并存储名称数组用于取消操作中的比较...

最后我们看下取消操作,防止用户不进行选择,导致di缺失的问题...        

cancelGoodsName() {
				let curArr = this.pageData.goodsName.split('/')
				let TargetArr = this.pageData.goodsNameArr
				if(curArr.length != TargetArr.length) {
					this.pageData.goodsName = ''
				}
				curArr.forEach((item,index) => {
					if(item != TargetArr[index]) this.pageData.goodsName = ''
				})
				this.showGoodsNamePic = false
			}

到这里,功能就基本实现了,代码纯手写,喜欢的可以给个star...

猜你喜欢

转载自blog.csdn.net/m0_52510500/article/details/132361248
今日推荐