vue3+uniapp+uview 

vue3 uview框架:https://vkuviewdoc.fsq.pub/components/picker.html

 

<template>
	<view class="main">
		<view class="mt25 all-menu box-shadow border-radius5">
			<text class="title mb10">全部菜单</text>

			<view class="x-p-titleList">
				<u-sticky>
					<!-- 只能有一个根元素 -->
					<view class="sticky">
						<u-tabs :list="dataList" :is-scroll="true" v-model="current" @change="change">
						</u-tabs>
					</view>
				</u-sticky>

				<scroll-view class="scroller mt5" :scroll-into-view="toView" scroll-y="true"
					scroll-with-animation="true">
					<view class="x-p-listItem" v-for="item in dataList" :key="item.id" :id="item.id">
						<u-line color="#bbbbbb" />
						<view class="mt5 mb5">{{item.name}}</view>
						<view v-for="info in item.moduleList" :key="info.moduleId"
							class="listItem-dtl u-icon-wrap u-row-between">
							<view class="u-flex">
								<image :src="info.icon"></image>
								<text>{{info.label}}</text>
							</view>
							<view>
								<u-button type="primary" class="add-btn" v-if="isAdd">添加</u-button>
								<u-button class="add-btn" v-else>已添加</u-button>
							</view>
						</view>
					</view>
				</scroll-view>
			</view>
		</view>


	</view>
</template>
<script lang="ts">
	import {
		ref,
		reactive,
		onMounted,
	} from 'vue'
	export default {
		setup() {
			const keyword = ref('')
			// ----------------------------------------
			const current = ref(0)
			const dataList = reactive([{
				id: 'item1',
				name: '办公OA',
				moduleList: [{
						moduleId: '5001',
						label: '出差申请',
						icon: '../../static/logo.png'
					},
					{
						moduleId: '5002',
						label: '加班申请',
						icon: '../../static/images/nav_car_apply.png'
					},
					{
						moduleId: '5003',
						label: '请假申请',
						icon: '../../static/images/nav_car_apply.png'
					},
					{
						moduleId: '5004',
						label: '办公用品申请',
						icon: '../../static/images/nav_car_apply.png'
					}
				]
			}, {
				id: 'item2',
				name: '生产管理',
				moduleList: [{
						moduleId: '6001',
						label: '生产',
						icon: '../../static/logo.png'
					},
					{
						moduleId: '6002',
						label: '领料',
						icon: '../../static/images/nav_car_apply.png'
					},
					{
						moduleId: '6003',
						label: '销售出库',
						icon: '../../static/images/nav_car_apply.png'
					},
					{
						moduleId: '6004',
						label: '销售入库',
						icon: '../../static/images/nav_car_apply.png'
					},
					{
						moduleId: '6004',
						label: '销售入库',
						icon: '../../static/images/nav_car_apply.png'
					}
				]
			}, {
				id: 'item3',
				name: '进销存管理',
				moduleList: [{
						moduleId: '5001',
						label: '出差申请',
						icon: '../../static/logo.png'
					},
					{
						moduleId: '5002',
						label: '加班申请',
						icon: '../../static/images/nav_car_apply.png'
					},
					{
						moduleId: '5003',
						label: '请假申请',
						icon: '../../static/images/nav_car_apply.png'
					},
					{
						moduleId: '5004',
						label: '办公用品申请',
						icon: '../../static/images/nav_car_apply.png'
					}
				]
			}, {
				id: 'item4',
				name: '供应商管理',
				moduleList: [{
						moduleId: '6001',
						label: '生产',
						icon: '../../static/logo.png'
					},
					{
						moduleId: '6002',
						label: '领料',
						icon: '../../static/images/nav_car_apply.png'
					},
					{
						moduleId: '6003',
						label: '销售出库',
						icon: '../../static/images/nav_car_apply.png'
					},
					{
						moduleId: '6004',
						label: '销售入库',
						icon: '../../static/images/nav_car_apply.png'
					},
					{
						moduleId: '6004',
						label: '销售入库',
						icon: '../../static/images/nav_car_apply.png'
					}
				]
			}, {
				id: 'item5',
				name: '实验室管理',
				moduleList: [{
						moduleId: '6001',
						label: '生产',
						icon: '../../static/logo.png'
					},
					{
						moduleId: '6002',
						label: '领料',
						icon: '../../static/images/nav_car_apply.png'
					},
					{
						moduleId: '6003',
						label: '销售出库',
						icon: '../../static/images/nav_car_apply.png'
					},
					{
						moduleId: '6004',
						label: '销售入库',
						icon: '../../static/images/nav_car_apply.png'
					},
					{
						moduleId: '6004',
						label: '销售入库',
						icon: '../../static/images/nav_car_apply.png'
					}
				]
			}, {
				id: 'item6',
				name: '生产管理',
				moduleList: [{
						moduleId: '6001',
						label: '生产',
						icon: '../../static/logo.png'
					},
					{
						moduleId: '6002',
						label: '领料',
						icon: '../../static/images/nav_car_apply.png'
					},
					{
						moduleId: '6003',
						label: '销售出库',
						icon: '../../static/images/nav_car_apply.png'
					},
					{
						moduleId: '6004',
						label: '销售入库',
						icon: '../../static/images/nav_car_apply.png'
					},
					{
						moduleId: '6004',
						label: '销售入库',
						icon: '../../static/images/nav_car_apply.png'
					}
				]

			}])
			let toView = ref('')
			// 锚点
			function change(index) {
				// var id = event.currentTarget.dataset.id;
				var id = 'item' + (index + 1)
				toView = id;
				uni.createSelectorQuery().select('#' + toView).boundingClientRect(data => { //目标位置的节点:类或者id
					uni.createSelectorQuery().select(".x-p-titleList").boundingClientRect(
						res => { //最外层盒子的节点:类或者id
							uni.pageScrollTo({
								duration: 100, //过渡时间
								// scrollTop: data.top - res.top - 10 //到达距离顶部的top值
								scrollTop: data.top - res.top + 45 //到达距离顶部的top值
							})
						}).exec()
				}).exec();
			}
			let isAdd = ref(true)
			// --------------------------------------
			let distanceArr = reactive([]) // 每一个ID对应的scrollTop值
			// 获取所有元素在当前页面所处的位置信息


			function getDistanceArr() {
				dataList.map(el => {
					uni.createSelectorQuery().select('#' + el.id).boundingClientRect(data => { //目标位置的节点:类或者id
						// 获取当前ID距离顶部的top值
						distanceArr.push(data.top)
					}).exec();
				})
			}
			// 生命周期
			onMounted(() => {
				getDistanceArr()
			})


			return {
				keyword,
				current,
				dataList,
				toView,

				change,
				isAdd,
				distanceArr,
				getDistanceArr
			}
		},
		// onShow() {
		// 	this.getDistanceArr()
		// },
		// 监听页面滚动
		onPageScroll(event) {
			const _this = this
			if (this.isTabChange) {
				return
			}
			const {
				scrollTop
			} = event;
			const skewY =100 // 偏移量,由于吸顶的tab、头部的显示信息也有高度,素以做了偏移量
			if (scrollTop >= skewY) {
				if (!this.showTabs && this.current <= 0) { // 在未显示tab并且 current <= 0时,防止uview ui抖动bug,设置默认复位值
					this.current = 0
				}
				this.showTabs = true
				this.$nextTick(() => {
					const length = this.distanceArr.length
					const index = this.distanceArr.findIndex(el => el - skewY - scrollTop > 0)
					// 当index  == -1 的时候,实际当前滚动的距离超出了最大值,也就是在最后一个tab显示的内容
					// 当index > 0 的时候,说明能在当前的scrollTop值找到,即index的前一位
					// this.current = index > 0 ? index - 1 : length - 1
					this.current = index > 0 ? index - 1 : 0
				})
			}
			//  else {
			// 	this.showTabs = false
			// }
		}
	}
</script>

<style lang="scss">
	.main {
		padding: 20rpx;
	}

	.all-menu {
		padding: 10rpx;

		.title {
			font-size: 16px;
			// font-weight: bold;
		}
	}

	// --------------------

	.list-cell {
		display: flex;
		box-sizing: border-box;
		width: 100%;
		padding: 10px 24rpx;
		color: #323233;
		font-size: 14px;
		line-height: 24px;
		background-color: #fff;
	}

	.listItem-dtl {
		height: 100rpx;


		image {
			height: 80rpx;
			width: 80rpx;
			margin-right: 16rpx;
		}
	}

	.search {
		position: fixed;
	}

	.scroller {
		box-sizing: border-box;
		padding: 0 15rpx;
	}
</style>

调用接口使用过程中的问题及解决

1.使用vue3赋值问题:

let dataList=reactive([])改成let obj=reactive({dataList:[]})

html部分修改:obj.dataList


<u-tabs :list="obj.dataList" :is-scroll="true" v-model="current" @change="change">
						</u-tabs>


<view class="x-p-listItem" v-for="(item,idxBlock) in obj.dataList" :key="item.menuId"
						:id="'item'+idxBlock">

2.js


	import {
		ref,
		reactive,
		onMounted,
		nextTick
	} from 'vue'

export default {
		setup() {

let obj = reactive({
				dataList: []
			})


			// 获取全部菜单列表
			function getAllMenuList() {
				listMenu(queryParams).then(res => {
					let data = res.data.data.map(s => {
						s.visible = false
						return s
					})
					let arr = handleTree(data, 'menuId')
					let newArr = []
					arr.forEach(item => {
						item.name = item.menuName
						item.id = item.menuId
						if (item.menuType != 'C') {
							newArr.push(item)
						}
					})
					obj.dataList = newArr
					
					// 记录每个模块节点位置,请求到数据挂在完成后执行,去掉原来的getDistanceArr方法
					nextTick(() => {
						obj.dataList.map((el, index) => {
							uni.createSelectorQuery().select('#item' + index).boundingClientRect(
								data => { //目标位置的节点:类或者id
									// 获取当前ID距离顶部的top值
									distanceArr.push(data.top)
								}).exec();
						})
					})

				})
			}


			// 生命周期
			onMounted(() => {
				getAllMenuList()
				// getDistanceArr()
			})


			return {
				keyword,
				current,
				obj,
				toView,

				change,
				isAdd,
				distanceArr,
				addOrCancelMenu,
			}
		},

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐