uniapp的vite模板中使用uni.createSelectorQuery().in(this)

在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;
    };

实现效果:
在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
UniApp是一个跨平台的移动应用开发框架,其内置了WebSocket模块,提供了简单易用的WebSocket封装。 UniApp的WebSocket封装可以方便开发者在应用使用WebSocket通信。使用WebSocket可以实现实时的双向通信,非常适合需要实时更新数据的场景,比如聊天应用、实时数据推送等。 UniApp的WebSocket封装提供了以下几个常用的方法: 1. connect(options):用于连接WebSocket服务器。开发者需要传入服务器的URL和其他选项,如心跳间隔、子协议等。 2. onOpen(callback):用于监听WebSocket连接成功的事件。当连接成功时,可以执行回调函数的代码。 3. onError(callback):用于监听WebSocket发生错误的事件。当连接过程出现错误时,可以执行回调函数的代码,进行错误处理。 4. onMessage(callback):用于监听WebSocket接收到消息的事件。当接收到消息时,可以执行回调函数的代码,对消息进行处理。 5. send(data):用于向WebSocket服务器发送消息。开发者可以传入字符串或二进制数据作为参数。 6. close():关闭WebSocket连接。调用该方法后,WebSocket将会关闭连接,并触发onClose事件。 UniApp的WebSocket封装使得开发者能够轻松地使用WebSocket进行实时通信。开发者只需要通过调用相应的方法,传入相应的参数,即可完成WebSocket的连接、消息发送、接收和关闭等操作。同时,UniApp还提供了方便的事件监听机制,能够在连接状态发生变化或接收到消息时执行相应的回调函数。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山为樽水为沼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值