caso de desplazamiento doble de uniapp

El desplazamiento doble se usa a menudo en los centros comerciales

En este ejemplo, los componentes de vista de desplazamiento izquierdo y derecho se utilizan para realizar desplazamiento doble

Las representaciones son las siguientes

En este ejemplo, la parte derecha adopta la visualización de una sola fila, que se siente mejor que la de dos filas. Puede mostrar la imagen por completo y la visualización no será antiestética debido a la diferente longitud del título.

 

Tenga en cuenta que algunos componentes son componentes personalizados, puede eliminar o reemplazar sus propios componentes, este ejemplo es solo un código de muestra.

<template>
    <view class="bg color-555">
	<mo-nav isBarHeight>
		<view class="flex flex-row bgColor-whites flex-items-center" @click="$mo.pageto('/pagesA/shop/carlists')">
			<view class="headbtn flex flex-row">
				<mo-icon name="gouwuche" size="20"></mo-icon>
			</view>
			<view class="marlr10">购物车</view>
		</view>
	</mo-nav>
			<view class="mo-wrap">
			
			    <view class="mo-search-box">
			    	<mo-search v-model="sotext" bgColor="#ffffff" @search="soso" @confirm="soso"></mo-search>
			    </view>
			    <view class="mo-menmo-wrap">
			        <scroll-view scroll-y scroll-with-animation class="mo-tab-view menmo-scroll-view bg" :scroll-top="scrollTop">
			            <view v-for="(item,index) in categoryBox" :key="index" class="mo-tab-item" 
						 :class="[current==index ? 'mo-tab-item-active' : '']"
			             @tap.stop="swichMenu(index)">
			                <text class="flex-wrap any-font-size-14">{
   
   {item.name}}</text>
						</view>
						<mo-gap :gap="60"></mo-gap> 
			        </scroll-view>
			
			        <scroll-view scroll-y scroll-with-animation class="right-box flex-1" :scroll-top="scrollRightTop" @scroll="rightScroll">
			            <view class="page-view">
			                <view class="class-item" :id="'item' + index" 
							v-for="(item , index) in categoryBox" :key="index">
			                    <view class="item-title">
									<view v-if="item.thumb" class="width-bb"
									 @click="item.click>0?$mo.pageto('/pagesA/shop/listso?id='+item.id):''">
								<image :src="$comjs.api.uploadsUrl+item.thumb" mode="widthFix" class="width-bb" style="height: auto;"></image>		
									</view>
			                        <view class="any-font-size-14" @click="item.click>0?$mo.pageto('/pagesA/shop/listso?id='+item.id):''">{
   
   {item.name}}</view>
			                    </view>
			                    
				<view v-for="(items,indexs) in item.data" :key="indexs">
					<view class="martb10 flex flex-row  flex-items-center" @click="$mo.pageto('/pagesA/shop/show?id='+items.id+'&catid='+items.catid)">
							<view>
								<image :src="items.thumb?$comjs.api.uploadsUrl+items.thumb:'../../static/300.png'" mode="aspectFill" class="thumb"></image>
							</view>
							<view class="flex flex-column flex-1 any-padding-10">
								<view class="any-font-size-12 flex-wrap">{
   
   {items.title}}</view>
								<view class="flex flex-between martb10">
									<view class="color-red">
										<text class="any-font-size-14">¥</text>
										<text class="any-font-size-16">{
   
   {items.money}}</text>
									</view>
									<view class="text-right">
										<mo-icon name="shaogouwu" size="20"></mo-icon>
									</view>
								</view>
							</view>
							
					</view>
				</view>
				<view v-if="!item.data.length" class="martb10 text-center color-ccc">- 暂无商品 -</view>
				<view v-else-if="item.data.length>=6&&item.click>0" class="martb10 text-center"
				 @click="$mo.pageto('/pagesA/shop/listso?id='+item.id)">查看更多</view>
				 <mo-gap :gap="10"></mo-gap>
				<mo-divider></mo-divider>
				
			                </view>
			            </view> 
						<mo-gap :gap="60"></mo-gap>
			        </scroll-view>
			
			    </view>
			    <!-- tabbar占位高度 -->
		
			</view>
			<mo-loading ref="loading"></mo-loading>
    </view>
</template>

<script>
var num = 0;
var dsq = null;

export default {
    components: {

    },
    data() {
        return {
            //systemInfo:base.systemInfo,
            isPopup:false,
            PrimaryColor:'#fe461d',//主题色
            categoryBox:[],//分类商品
            current: 0,
            scrollTop:0,
            specGoodsData:{},//选择的规格数据
            
            // ***滑动联动所需参数***
            oldScrollTop: 0,
            current: 0, // 预设当前项的值
            menuHeight: 0, // 左边菜单的高度
            menuItemHeight: 0, // 左边菜单item的高度
            itemId: '', // 栏目右边scroll-view用于滚动的id
            menuItemPos: [],
            arr: [],
            scrollRightTop: 0, // 右边栏目scroll-view的滚动高度
            timer: null, // 定时器
            flag:false,//禁止current两次赋值
            flag2:true,//是否禁止右侧滑动
            c_id:'',//跳转的参数--定位分类id位置
			sotext:''
        }
    },
    onLoad(e) {
        // this.c_id = e.c_id
    	//this.c_id = 9 //跳转的参数--定位分类id位置
        
    },
    onReady() {
    	this.getMenuItemTop()
    },
    onShow(){
		let that=this;
		//加载药品列表
		this.getgoodsList()
		
    	// #ifndef MP-ALIPAY
    	num = 0;
    	this.DSQ()
    	// #endif
    },
    methods: {
		soso(){
			let that=this;
			that.$comjs.pageto("/pagesA/shop/listso",{},function(res){
				res.eventChannel.emit('sotext', { sotext:that.sotext})
			});
		},
        getgoodsList() {
			let that=this;
			that.$comjs.http(that,that.$comjs.api.shop,{},false,redata=>{
				that.categoryBox=redata.data;
				// 如果有传分类c_id参数-滑动到对应的选项
				if(that.sotext){
					let currItem=that.categoryBox.find(item=>{
						return item.data.find(items=>{
							return items.name==that.sotext;
						})		
					})
					if(currItem){
						console.log(currItem,11111)
						that.c_id=currItem.id;
						that.categoryBox.forEach((item,index)=>{
						    if(item.id == that.c_id){
						        let time =500 //实际接口这里数字可以调小点
						        // 等待页面渲染完成
						        setTimeout(()=>{
						            if(index>=2){
						                that.swichMenu(index-1)
						            }
						        },time) 
						        setTimeout(()=>{
						            that.swichMenu(index)
						        },time+200)
						    }
						})
					}
				}
				
			});
        },
        // 点击左边的栏目切换
        async swichMenu(index) {
            console.log('swichMenu')
            // #ifdef MP-ALIPAY
            if(index == this.current) return ;
            this.current = index;
            // 如果为0,意味着尚未初始化
            if(this.menuHeight == 0 || this.menuItemHeight == 0) {
                await this.getElRect('menmo-scroll-view', 'menuHeight');
                await this.getElRect('mo-tab-item', 'menuItemHeight');
            }
            // 将菜单菜单活动item垂直居中
            this.scrollTop = index * this.menuItemHeight + this.menuItemHeight / 2 - this.menuHeight / 2;
            // #endif
            // #ifndef MP-ALIPAY
            if(this.arr.length == 0) {
                await this.getMenuItemTop();
            }
            if (index == this.current) return;
            this.scrollRightTop = this.oldScrollTop;
            this.$nextTick(function(){
                this.scrollRightTop = this.arr[index];
                this.current = index;
                this.flag = true
                this.flag2 = false //禁止右侧滑动
                this.leftMenuStatus(index);
                num = 0
            })
            // #endif
        },
        DSQ(isClear){
            // 解决点击分类,左侧多次滚动
            dsq && clearInterval(dsq)
            dsq = setInterval(()=>{
                num+=100
                if(num>500){
                    this.flag2 = true
                }
                // console.log(num)
            },100)
        },
        // 获取一个目标元素的高度
        getElRect(elClass, dataVal) {
            new Promise((resolve, reject) => {
                const query = uni.createSelectorQuery().in(this);
                query.select('.' + elClass).fields({size: true},res => {
                    // 如果节点尚未生成,res值为null,循环调用执行
                    if(!res) {
                        setTimeout(() => {
                            this.getElRect(elClass);
                        }, 10);
                        return ;
                    }
                    this[dataVal] = res.height;
                }).exec();
            })
        },
        // ***********************************************  微信小程序 S  *****************************************************************
        // 设置左边菜单的滚动状态
        async leftMenuStatus(index) {
            console.log('左侧滚动')
            // #ifndef MP-ALIPAY
            if(this.flag){
                this.current = index;
                this.flag = false
                console.log(index)
            }
            // 如果为0,意味着尚未初始化
            if (this.menuHeight == 0 || this.menuItemHeight == 0) {
                await this.getElRect('menmo-scroll-view', 'menuHeight');
                await this.getElRect('mo-tab-item', 'menuItemHeight');
            }
            console.log(this.menuHeight,'this.menuHeight')
            console.log(this.menuItemHeight,'this.menuItemHeight')
            // 将菜单活动item垂直居中
            this.scrollTop = index * this.menuItemHeight + this.menuItemHeight / 2 - this.menuHeight / 2;
            // #endif
        },
        // 获取右边菜单每个item到顶部的距离
        getMenuItemTop() {
            // #ifndef MP-ALIPAY
            new Promise(resolve => {
                let selectorQuery = uni.createSelectorQuery();
                selectorQuery.selectAll('.class-item').boundingClientRect((rects) => {
                    // 如果节点尚未生成,rects值为[](因为用selectAll,所以返回的是数组),循环调用执行
                    if(!rects.length) {
                        setTimeout(() => {
                            this.getMenuItemTop();
                        }, 10);
                        return ;
                    }
                    rects.forEach((rect) => {
                        // 这里减去rects[0].top,是因为第一项顶部可能不是贴到导航栏(比如有个搜索框的情况)
                        this.arr.push(rect.top - rects[0].top);
                        resolve();
                    })
                }).exec()
            })
            // #endif
        },
        // 右边菜单滚动
        async rightScroll(e) {
            // #ifndef MP-ALIPAY
            if(this.flag2 && !this.flag){
                 console.log('右侧滚动')
                this.oldScrollTop = e.detail.scrollTop;
                if(this.arr.length == 0) {
                    await this.getMenuItemTop();
                }
                if(this.timer) return ;
                if(!this.menuHeight) {
                    await this.getElRect('menmo-scroll-view', 'menuHeight');
                }
                setTimeout(() => { // 节流
                    this.timer = null;
                    // scrollHeight为右边菜单垂直中点位置
                    let scrollHeight = e.detail.scrollTop + this.menuHeight / 2;
                    for (let i = 0; i < this.arr.length; i++) {
                        let height1 = this.arr[i];
                        let height2 = this.arr[i + 1];
                        // 如果不存在height2,意味着数据循环已经到了最后一个,设置左边菜单为最后一项即可
                        if (!height2 || scrollHeight >= height1 && scrollHeight < height2) {
                            this.flag = true
                            this.leftMenuStatus(i);
                            return ;
                        }
                    }
                }, 10)
            }
            // #endif
        },
        // ***********************************************  微信小程序 E  *****************************************************************
    },

}
</script>

<style lang="scss" scoped>
.headbtn {
	border-radius: 20px;
	margin-left: 15px;
}

.bg {
	background: #edf4f7;
}	
.leftque{color:red;display: inline-block;margin-right:2px;border-radius:50%;background-color: #fff;border:1px solid red;width:10px;height:10px;padding:2px;}
.mo-wrap {
    height: calc(100vh);
    /* #ifdef H5 */
    height: calc(100vh - var(--window-top));
    /* #endif */
    /* #ifndef APP-NVUE */
    display: flex;
    /* #endif */
    flex-direction: column;
}
.mo-search-box {
    padding: 0rpx 20rpx 15rpx 20rpx;
	margin-top:140rpx;
}
.mo-search-inner {
    background-color: #f5f5f5;
    border-radius: 100rpx;
    /* #ifndef APP-NVUE */
    display: flex;
    /* #endif */
    align-items: center;
    padding: 10rpx 16rpx;
}
.mo-search-text {
    color: #999;
    margin-left: 10rpx;
}

.mo-menmo-wrap {
    flex: 1;
    /* #ifndef APP-NVUE */
    display: flex;
    /* #endif */
    overflow: hidden;
	
}
.mo-tab-view {
	width: 160rpx;
    height: 100%;
}
.mo-tab-item {
    width: 160rpx;
    // height: 110rpx;
    padding:15px 8px;
    box-sizing: border-box;
    /* #ifndef APP-NVUE */
    display: flex;
    /* #endif */
    align-items: center;
    font-weight: 400;
    line-height: 1;
    position: relative;
	z-index: 10;
    .cartNumber{
        position: absolute;
		z-index: 10;
        border-radius: 34rpx;
        top: 8rpx;
        right: 8rpx;
        // width: 34rpx;
        padding: 0 10rpx;
        height: 34rpx;
        line-height: 34rpx;
        background: #508c22;
        color: #fff;
    }
    text{
        line-height: 1.2;
    }
}
.mo-tab-item-active {
    position: relative;
	z-index: 10;
 
    color:#333;
    background: #fff;
    .title{
        color: #D54F4F
    }
}
.mo-tab-item-active::before {
    content: "";
    position: absolute;
	z-index: 10;
    border-left: 4rpx solid #D54F4F;
    height: 32rpx;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
}
.mo-tab-view {
    height: 100%;
}
.right-box {
    /* #ifdef MP-ALIPAY */
   
    /* #endif */
    /* #ifndef MP-ALIPAY */
   
    /* #endif */
	.thumb{width:68px;height:68px;border-radius:8px;}
}
.page-view {
    // padding: 16rpx;
}
.class-item {
    // margin-bottom: 30rpx;
    background-color: #fff;
    padding:10px 5px;
    border-radius: 8rpx;
    /* #ifndef MP-ALIPAY */
    padding-bottom: 20rpx;
    /* #endif */
}
.item-title {
    color: #333;
    text{
        color: #999;
    }
}
.item-menmo-name {
    font-weight: normal;
    color: #333;
}
.item-container {
    /* #ifndef APP-NVUE */
    display: flex;
    /* #endif */
    flex-wrap: wrap;
}
</style>

VUE3 básico, los componentes de interfaz de usuario compatibles con VUE2 están en desarrollo y estarán disponibles para que todos los usen de forma gratuita.

El siguiente es un ejemplo de un subprograma de gestión de proyectos personales que utiliza este componente

 

Supongo que te gusta

Origin blog.csdn.net/qq_41589481/article/details/125848858
Recomendado
Clasificación