赞
踩
在vite模板中使用uni.createSelectorQuery().in(this)来获取节点信息时,由于this不存在,需要找一个替代方法传进去。
import { getCurrentInstance, reactive } from 'vue'; const instance = getCurrentInstance(); const getItemDistence = () => { letselectQuery = uni.createSelectorQuery().in(instance); selectQuery.selectAll('.menu-item').boundingClientRect((rect:any)=>{ if(!rect.length){ setTimeout(()=>{ getItemDistence(); },10); return; } rect.forEach((it:any)=>{ state.itemArr.push(it); // 这里获取到的数据是每个item距离页面顶部的数据,以及每个item的自身数据 }) }).exec() }
uni.createSelectorQuery().in(this)用来实现滚动菜单效果,默认菜单是存在数据的情况,所以不会存在死循环的。
html部分
<view class="container-wrap"> <view class="left" v-if="state.navBarLeftIcon !== 'grid'"> <scroll-view class="fill" scroll-y="true" scroll-with-animation :scroll-into-view="state.clickId"> <view v-for="(item,index) in state.dataList" :key="index+'left'" :id="'left'+index" class="left-item" :class="state.picked == index ? 'checkedStyle' : ''" @click="selectActiveEvt(index)"> {{item.name}} </view> </scroll-view> </view> <view class="right"> <scroll-view class="fill" scroll-y="true" scroll-with-animation :scroll-into-view="state.clickId" @scroll="scrollEvt"> <view class="menu-item" v-for="(item,index) in state.dataList" :key="index+'right'"> <uni-section :title="item.name" type="line" :titleFontSize="'30rpx'" :id="'left' + index"> <up-grid :col="state.navBarLeftIcon !== 'grid' ? 3 : 4" :border="false"> <up-grid-item v-for="(menu,menuIndex) in item.children" :index="menuIndex" :key="'item' + menuIndex" @click="goPath(menu.pageUrl)"> <view class="grid-item-box mb-30"> <image class="image" :src="menu.icon ? fileUrl + JSON.parse(menu.icon)[0].url : ''" mode="aspectFill" /> <text class="text">{{menu.name}}</text> </view> </up-grid-item> </up-grid> </uni-section> </view> </scroll-view> </view> </view>
css
.container-wrap { display: flex; } .left { width: 25%; height: 100%; margin-right: 10rpx; background-color: #ffffff; .left-item { height: 90rpx; box-sizing: border-box; text-align: center; line-height: 90rpx; color: black; font-weight: 600; font-size: 28rpx; } .checkedStyle{ background-color: #eef3f7; border-left: 4rpx solid #007AFF; box-sizing: border-box; color: #007AFF; } } .right { background-color: #fff; flex: 1; height: 100%; } .grid-item-box { display: flex; flex-direction: column; align-items: center; .image { width: 50rpx; height: 50rpx; } .text { font-size: 28rpx; margin-top: 10rpx; } }
ts代码
import { getCurrentInstance, reactive } from 'vue'; import { onLoad, onShow } from "@dcloudio/uni-app"; import sendRequest from '@/utils/sendRequest'; import { jumpPage } from '@/utils/tools'; import base from '@/utils/base'; const fileUrl = base.fileUrl; const state = reactive({ navBarLeftIcon: 'list' as string, showPopup: false, dataList: [] as any [], // 列表数据 clickId: 'left0', // 点击选项的id picked: 0, // 左侧选中index nowRightIndex: 0, // 右边当前滚动的index itemArr: [] as any, // 用于存放右侧item位置数据 timer: null as any, isScroll: true, }); const instance = getCurrentInstance(); onLoad((options) => { setTimeout(()=>{ getItemDistance(); },1000) }); onShow(() => { state.dataList = uni.getStorageSync('menuList'); }); // 计算右侧每个item到顶部的距离,存放到数组 const getItemDistance = () => { let selectQuery = uni.createSelectorQuery().in(instance); selectQuery.selectAll('.menu-item').boundingClientRect((rect:any)=>{ if(!rect.length){ setTimeout(()=>{ getItemDistance(); },10); return; } rect.forEach((it:any)=>{ state.itemArr.push(it); // 这里获取到的数据是每个item距离页面顶部的数据,以及每个item的自身数据 }) }).exec() } // 节流 const scrollEvt = (e:any) =>{ if(state.timer){ clearTimeout(state.timer); } if(!state.isScroll) { state.isScroll = true; return; } state.timer = setTimeout(()=>{ // 判断当前顶部是处于哪个item,获取当前item的index let i:number = -1; state.itemArr.map((it:any, index:number) => { if(e.detail.scrollTop >= (it.bottom - 412)) { i = index; } }); state.nowRightIndex = i > -1 ? i : 0; if(state.nowRightIndex == -1) state.nowRightIndex = 0; if(state.nowRightIndex == state.picked) return; if(state.isScroll) { state.isScroll = false; state.clickId = 'left' + state.nowRightIndex; state.picked = state.nowRightIndex; } },100); } // 选中左侧菜单 const selectActiveEvt = (index:number) => { state.clickId = 'left' + index; state.picked = index; state.isScroll = false; }; // 选中功能条目 const slectItem = (type: string) => { console.log(type); state.showPopup = false; }; // 页面跳转 const goPath = (path:string) => { jumpPage(path, 'navigateTo'); } // 点击左侧区域 const leftClick = () => { if(state.navBarLeftIcon === 'grid') { state.navBarLeftIcon = 'list'; } else { state.navBarLeftIcon = 'grid'; } }; // 点击右侧区域 const rightClick = () => { state.showPopup = !state.showPopup; };
实现效果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。