uniapp 微信小程序 懒加载多级城市联动

本文详细描述了如何在uniapp微信小程序中使用懒加载策略实现一个多级联动的城市选择器组件,包括模板结构、数据处理和组件交互逻辑,以提高性能和用户体验。
摘要由CSDN通过智能技术生成

uniapp 微信小程序 懒加载多级城市联动:

子组件

<template>
   <view class="data-picker">
   	<view class="slot">
   		<slot>

   		</slot>
   	</view>
   	<view class="data-picker-cont" @tap="handleShowPicker">
   		<text v-if="!data.activeName" class="pl">{{props.promptText}}</text>
   		<text v-if="data.activeName">{{data.activeName}}</text>
   		<uni-icons type="right" size="18" color="#222"></uni-icons>
   	</view>
   </view>


   <view class="data-picker-mark" v-if="data.show" @tap="handleClosePicker">
   	<view class="data-picker-mark-cont" @tap.stop.prevent="">
   		<view class="data-picker-mark-cont-header">
   			<view></view>
   			<view class="data-picker-mark-cont-header-title">请选择{{props.promptText}}</view>
   			<view class="data-picker-mark-cont-header-close" @tap="handleClosePicker">
   				<uni-icons type="closeempty" size="20" color="#858585"></uni-icons>
   			</view>
   		</view>
   		<view class="data-picker-mark-cont-tab">
   			<view v-for="(item,index) in data.tab" :key="index" @tap="handleTab(item)"
   				class="data-picker-mark-cont-tab-item "
   				:class="{'data-picker-mark-cont-tab-item-active':item.level==data.activeLevel}">{{item.label}}
   			</view>
   		</view>
   		<view class="data-picker-mark-cont-wrap">
   			<view class="data-picker-mark-cont-wrap-item" v-for="(item,index) in compAcitveLevelList" :key="index"
   				@tap="handleAdd(item)">
   				{{item[props.label]}}
   			</view>
   		</view>
   	</view>
   </view>
</template>

<script setup>
   import {
   	onMounted,
   	reactive,
   	computed,
   	watch
   } from 'vue'
   /**
    * dataList 数据
    * label 要显示的字段
    * rangeKey id 唯一值
    * promptText 显示的文字
    */

   /**
    * 最后一层,通过父级组件调用load(row,[]) 第二个参数为空,自动结束递归
    */

   let props = defineProps(['dataList', 'label', 'rangeKey', 'promptText'])
   let emit = defineEmits(['load', 'nodeClick'])
   let data = reactive({
   	show: false,
   	wrapList: props.dataList,
   	tab: [{
   		level: 1,
   		label: '请选择',
   		value: '',
   		data: []
   	}],
   	activeLevel: 1, //当前层级
   })
   const watchList = watch(() => props.dataList, (value) => {
   	if (value && value.length > 0) {
   		data.tab[0].data = value
   		data.tab[0].data.forEach(item => item.level = 1)
   		watchList()
   	}
   }, {
   	deep: true
   })
   /**
    * 返回当前层级下的数据
    */
   let compAcitveLevelList = computed(() => {
   	if (data.activeLevel == 1) {
   		//第一层返回传递过来的数组
   		return props.dataList
   	} else {
   		let item = data.tab.find(item => item.level == data.activeLevel)
   		if (item && item.data) {
   			return item.data
   		} else {
   			return []
   		}
   	}

   })
   onMounted(() => {
   	data.wrapList = props.dataList
   })
   /**
    * 获取懒加载的数据
    */
   function load(parentObj, rows) {
   	let nextLevel = parentObj.level + 1
   	rows.forEach(item => {
   		item.level = nextLevel
   		item.parentId = parentObj[props.rangeKey]
   	})
   	let index = parentObj.level - 1
   	data.tab[index].label = parentObj.text
   	data.tab[index].value = parentObj.value
   	if (rows.length <= 0) {
   		nodeClick()
   		return false
   	}
   	let is = data.tab.find(item => item.label == '请选择')
   	if (!is) {
   		data.tab.push({
   			level: nextLevel,
   			label: '请选择',
   			data: rows
   		})
   	} else {
   		let item = data.tab.find(item => item.level == nextLevel)
   		item.data = []
   		item.data = rows
   	}
   	data.activeLevel = nextLevel
   }
   /**
    * 点击最后一层,关闭组件返回内容
    */
   function nodeClick() {
   	let e = {}
   	e.value = data.tab.map(item => item.value)
   	e.label = data.tab.map(item => item.label)
   	data.activeName = e.label.join('-')
   	emit('nodeClick', e)
   	handleClosePicker()
   }
   /**
    * 点击项,获取子项
    * @param {Object} item
    */
   function handleAdd(item) {
   	//将子级的选项删除
   	data.tab = data.tab.filter(items => items.level <= item.level)
   	emit('load', item)
   }
   /**
    * 切换层级
    */
   function handleTab(item) {
   	data.activeLevel = item.level
   }
   /**
    * 点击关闭选择框
    */
   function handleClosePicker() {
   	data.show = false
   }
   /**
    * 点击展开选择框
    */
   function handleShowPicker() {
   	data.show = true
   }


   defineExpose({
   	load
   })
</script>

<style scoped lang="less">
   .data-picker {
   	width: 100%;
   	height: 100%;

   	&-cont {
   		width: 100%;
   		height: 100%;
   		display: none;
   		justify-content: space-between;
   		align-items: center;

   		.pl {
   			color: #858585;
   			font-size: 28upx;
   		}
   	}


   	&-mark {
   		position: fixed;
   		top: 0;
   		left: 0;
   		width: 100%;
   		height: 100vh;
   		background-color: rgba(0, 0, 0, .3);
   		z-index: 9;

   		&-cont {
   			position: absolute;
   			bottom: 0;
   			left: 0;
   			width: 100%;
   			height: auto;
   			max-height: 70vh;
   			padding: 0 30upx;
   			box-sizing: border-box;
   			background-color: #fff;
   			border-radius: 20upx 20upx 0 0;
   			z-index: 10;

   			&-header {
   				height: 100upx;
   				display: flex;
   				justify-content: space-between;
   				align-items: center;

   				&-title {
   					font-size: 30upx;
   					color: #222;
   				}
   			}

   			&-tab {
   				width: 100%;
   				height: 70upx;
   				border-bottom: 1upx solid #ebebeb;
   				overflow-x: auto;
   				white-space: nowrap;

   				&-item {
   					width: 100px;
   					display: inline-block;
   					height: 100%;
   					line-height: 70upx;
   					font-size: 30upx;
   					color: #222;
   					text-align: center;
   					margin-right: 20upx;

   					&-active {
   						position: relative;
   					}

   					&-active:after {
   						position: absolute;
   						content: '';
   						bottom: 0;
   						left: 0;
   						width: 100%;
   						height: 4upx;
   						background-color: #3653ff;
   					}
   				}
   			}

   			&-wrap {
   				height: 60vh;
   				overflow: auto;

   				&-item {
   					font-size: 28upx;
   					color: #222;
   					height: 70upx;
   					line-height: 70upx;
   				}
   			}
   		}
   	}

   }

   .slot:empty+.data-picker-cont {
   	//插槽为空,显示默认内容
   	display: flex !important;
   }
</style>

父组件

<dataPicker style="width:100%;height:100%" ref="dataPickerRef" 
:dataList="data.cityList"
:label="'text'" 
:rangeKey="'value'" 
:promptText="'服务地区'" 
@load="load" 
@nodeClick="nodeClick"></dataPicker>


 
	function load(row) {
		//获取城市数据 cityList
		 dataPickerRef.value.load(row, cityList)
	}



  function	nodeClick(e){
		console.log(e,'e')
		data.province_code = e.value[0]
		data.city_code = e.value[1]
		data.area_code = e.value[2]
		
		data.province_name = e.label[0]
		data.city_name = e.label[1]
		data.area_name = e.label[2]
		
		
		console.log(data,'data')
	}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当面试官问到uniapp微信小程序相关的试题时,你可以参考以下问题答案: 1. 什么是uniapp? - uniapp是一个基于Vue.js开发跨平台应用框架,可以同时开发iOS、Android、H5和微信小程序等多个平台的应用。 2. 什么是微信小程序? - 微信小程序是一种在微信平台上运行的应用程序,用户可以在微信中直接使用,无需下载安装。 3. uniapp微信小程序有什么关系? - uniapp可以开发微信小程序,通过uniapp的跨平台特性,开发者只需要编写一套代码,就可以同时在多个平台上运行。 4. uniapp开发微信小程序的优势有哪些? - 跨平台开发:只需编写一套代码,即可在多个平台上运行。 - 开发效率高:使用Vue.js进行开发,具有简洁、灵活的语法,提高开发效率。 - 统一的UI组件:uniapp提供了一套统一的UI组件库,方便开发者快速构建界面。 - 支持原生能力:uniapp支持调用原生API,可以实现更多的功能。 5. uniapp开发微信小程序的限制有哪些? - 对于一些特定的微信小程序API,uniapp可能无法直接调用,需要通过插件或自定义组件来实现。 - 由于不同平台的差异,一些特定的样式和功能在不同平台上可能会有差异。 6. uniapp中如何实现微信小程序的页面跳转? - 可以使用uniapp提供的`uni.navigateTo`、`uni.redirectTo`、`uni.switchTab`等方法来实现页面跳转。 7. uniapp中如何调用微信小程序的原生API? - 可以使用uniapp提供的`uni.request`、`uni.showToast`等方法来调用微信小程序的原生API。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值