uniapp 商品分类点击/滚动定位 scroll-view

左分类,右商品
左点击跳到其商品区 右滑动,左跳到其分类
在这里插入图片描述
左分类点击跳至其所有产品
scroll-into-view:值应为某子元素id (id不能以数字开头)。设置哪个方向可滚动,则在哪个方向滚动到该元素

右产品 通过滑动判断子元素位置 改变左侧分类已选状态
@scroll:滚动时触发,event.detail = {scrollLeft, scrollTop, scrollHeight, scrollWidth, deltaX, deltaY}
uni.createSelectorQuery :返回一个 SelectorQuery 对象实例。可以在这个实例上使用 select 等方法选择节点,并使用 boundingClientRect 等方法选择需要查询的信息。
scroll-view 属性链接

//左分类
<scroll-view scroll-y="true" class="scroll-Y" :scroll-into-view=tocate scroll-with-animation="true">
	<view :class="(index+1)==select_index?'item active':'item'" v-for="(item,index) in listData" :key="index" @click="selectCategory(item)" :id="'pro_'+item.id">
		<image :src="item.images.path"></image>
		<text>{{item.name}}</text>
	</view>
</scroll-view>

//右产品
<scroll-view scroll-y="true" class="scroll-Y scroll-3" :scroll-into-view=toview scroll-with-animation="true" @scroll="cateScroll">
	<view class="item aaaaa" v-for="(item,index) in childlist" :key="index" :id="'pro_'+item.id">
		<text class="cate_name">{{item.name}}</text>
		<view v-for="(item1,i) in item.productList" :key="i" class="list_pro">
			<image :src="item1.image[0].path" mode="aspectFit"></image>
			<view class="detail">
				<text class="type-name">{{item1.product_name}}</text>
				<text class="selling_point">{{item1.selling_point}}</text>
				<text class="price">¥{{item1.product_price}}</text>
				<text class="guige"  @click="addCart(item1)">加购</text>
			</view>
		</view>
	</view>
</scroll-view>
/*点击分类跳产品*/
selectCategory(e) {
	this.toview = 'pro_' + e.id
	this.select_index = e.sort
},

/*滑动产品改变分类已选*/
cateScroll() {
	const query = uni.createSelectorQuery().in(this);
	query.selectAll('.aaaaa').boundingClientRect(data => {
		for (var cate = 0; cate < data.length; cate++) {
			if (data[cate].top < 120 && data[cate].top > 0) {
				this.toview = data[cate].id;
				this.select_index = cate + 1;
			}
		}
	}).exec();
}

补上一份可以直接用的文件,之前数据都找不到了,写了份类似的加上数据结构,放进uniapp里可以直接运行起来看到效果

–2023/12/21


<template>
	 <view class="category-wrap">
		<view style="height: 20vh;background-color: aliceblue;">
			展示区
		</view>
		<view class="order_product">
		  <!--类别列表-->
		  <view class="category-content">
			<view class="cotegory-type cotegory-type-3">
			  <view class="category-tab">
				<scroll-view
				  scroll-y="true"
				  class="scroll-Y"
				  :scroll-into-view="tocate"
				  scroll-with-animation="true"
				>
				  <view
					:class="index == select_index ? 'item active' : 'item'"
					v-for="(item, index) in listData"
					:key="index"
					@click="selectCategory(item.category_id, index)"
					:id="'pro_' + item.category_id"
				  >
					<text style="white-space: pre;">{{ item.name.replace(' ','\n')}}</text>
					<view class="cate_num_all" v-if="item.cate_num_all">
					  <text>{{ item.cate_num_all }}</text>
					</view>
				  </view>
				</scroll-view>
			  </view>
			  <view class="category-content pr">
				<scroll-view
				  scroll-y="true"
				  class="scroll-Y scroll-3"
				  :scroll-into-view="toview"
				  scroll-with-animation="true"
				  @scroll="cateScroll"
				>
				  <block v-for="(item, index) in listData" :key="index">
					<view
					  v-if="item.name == '精选'+ ' ' + '套餐'"
					  :id="'pro_' + item.category_id">
					  <view
						v-for="(item1, i) in item.productList"
						:key="i"
						class="list_pro_one"
						@click="getdetail(item1.product_id, item1)"
					  >
						<image
						  class="pro_img_info"
						  :src="item1.image[0].file_path"
						  mode="scaleToFill"
						>
						</image>
						<view class="detail">
						  <view class="type-name">{{ item1.product_name }}</view>
						  <view class="selling_point">{{
							item1.selling_point
						  }}</view>
						  <view class="price">¥{{ item1.product_price }}</view>
						  <view
							v-if="item1.spec_type == 20"
							class="guige"
							@click.stop="getdetail(item1.product_id, item1)"
						  >
							{{ item1.product_stock ? "选规格" : "库存不足" }}
						  </view>
						  <view
							v-else
							class="guige_jj icon iconfont icon-jia"
							@click.stop="addCart(item1)"
						  ></view>
						</view>
					  </view>
					</view>
					<view v-else class="item aaaaa" :id="'pro_' + item.category_id">
					  <!-- <text class="cate_name">{{item.name}}</text> -->
					  <!-- item.titleimg -->
					  <image
						class="cate_name"
						v-if="item.titleimg"
						:src="item.titleimg.file_path"
					  >
					  </image>
					  <view
						v-for="(item1, i) in item.productList"
						:key="i"
						class="list_pro"
						:id="item1.product_id"
						@click="getdetail(item1.product_id, item1)"
					  > 
						<image
						  class="pro_img_info"
						  :src="item1.image[0].file_path"
						  mode="aspectFill"
						>
						</image>
						<view class="detail">
						  <text class="type-name">{{ item1.product_name }}</text>
						  <text class="selling_point">{{
							item1.selling_point
						  }}</text>
						  <text class="price">¥{{ item1.product_price }}</text>
						  <block>
							<text
							  v-if="item1.spec_type == 20"
							  class="guige"
							  @click.stop="getdetail(item1.product_id, item1)"
							  >{{
								item1.product_stock ? "选规格" : "库存不足"
							  }}</text
							>
							<text
							  v-else
							  class="guige_j icon iconfont icon-jia"
							  @click.stop="addCart(item1)"
							></text>
						  </block>
						</view>
					  </view>
					</view>
				  </block>
				</scroll-view>
			  </view>
			</view>
		  </view>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				toview: "",
				select_index: 0,
				listData: [
					{
						name:'大分类1',
						titleimg:{file_path:''}, //商品分类的展示图片
						category_id:'1',
						cate_num_all:'',
						productList:[
							{
								product_id:'200',
								product_name:'商品1',
								product_price:'20.00',
								selling_point:'好吃不贵',
								product_stock:false,
								image:[
									{
										file_path:''
									}
								]
							},
							{
								product_id:'201',
								product_name:'商品2',
								product_price:'22.00',
								selling_point:'好吃不贵',
								product_stock:false,
								image:[
									{
										file_path:''
									}
								]
							},
							{
								product_id:'208',
								product_name:'商品256',
								product_price:'22.00',
								selling_point:'好吃不贵',
								product_stock:false,
								image:[
									{
										file_path:''
									}
								]
							}
						]
					},
					{
						name:'大分类2',
						titleimg:{file_path:''},
						category_id:'2',
						cate_num_all:'',
						productList:[
							{
								product_id:'300',
								product_name:'23商品',
								product_price:'230.00',
								selling_point:'好吃不贵',
								product_stock:false,
								image:[
									{
										file_path:''
									}
								]
							},
							{
								product_id:'201',
								product_name:'12商品2',
								product_price:'223.00',
								selling_point:'好吃不贵',
								product_stock:false,
								image:[
									{
										file_path:''
									}
								]
							},
							{
								product_id:'204',
								product_name:'pocy',
								product_price:'23.00',
								selling_point:'好吃不贵',
								product_stock:false,
								image:[
									{
										file_path:''
									}
								]
							},
							{
								product_id:'205',
								product_name:'poc111y',
								product_price:'23.00',
								selling_point:'好吃不贵',
								product_stock:false,
								image:[
									{
										file_path:''
									}
								]
							},
						]
					},
					{
						name:'大分类3',
						titleimg:{file_path:''},
						category_id:'3',
						cate_num_all:'',
						productList:[
							{
								product_id:'400',
								product_name:'23商品',
								product_price:'230.00',
								selling_point:'好吃不贵',
								product_stock:false,
								image:[
									{
										file_path:''
									}
								]
							},
							{
								product_id:'401',
								product_name:'12商品2',
								product_price:'223.00',
								selling_point:'好吃不贵',
								product_stock:false,
								image:[
									{
										file_path:''
									}
								]
							},
							{
								product_id:'404',
								product_name:'23商品',
								product_price:'230.00',
								selling_point:'好吃不贵',
								product_stock:false,
								image:[
									{
										file_path:''
									}
								]
							},
							{
								product_id:'405',
								product_name:'测试2',
								product_price:'223.00',
								selling_point:'好吃不贵',
								product_stock:false,
								image:[
									{
										file_path:''
									}
								]
							}
						]
					},
				],
			}
		},
		methods:{
			/*选择分类*/
			selectCategory(e, index) {
				this.toview = "pro_" + e;
				this.select_index = index;
			},
			cateScroll() {
			  const query = uni.createSelectorQuery().in(this);
			  query.selectAll(".aaaaa")
			    .boundingClientRect((data) => {
			      for (var cate = 0; cate < data.length; cate++) {
			        if (data[cate].top < 200 && data[cate].top > 0) {
			          this.toview = data[cate].id;
			          this.select_index = cate;
			        }
			      }
			    })
			    .exec();
			},
		}
	}
</script>

<style lang="less">
	/**/
	.list_pro_one {
	  position: relative;
	  margin: 10px 20px 10px 0px;
	  image {
	    width: 100%;
	    height: 166px;
	    border-radius: 10px;
	  }
	
	  .detail {
	    width: 100%;
	    position: absolute;
	    top: 0;
	    padding: 18px 12px;
	    box-sizing: border-box;
	    color: #343434;
	    height: 100%;
	  }
	
	  .detail .type-name {
	    font-size: 18px;
	    //color: #343434;
	  }
	
	  .detail .selling_point {
	    font-size: 13px;
	    margin-top: 6px;
	  }
	
	  .detail .price {
	    font-size: 23px;
	    margin-top: 10px;
	    font-weight: bold;
	  }
	
	  .guige_jj {
	    background: #278D44;
	    color: #fff !important;
	    border-radius: 15px;
	    font-size: 10px;
	    padding: 5px;
	    position: absolute;
	    bottom: 20px;
	    right: 10px;
	  }
	}
	
	.guige_j {
	  background: #278D44;
	  color: #fff !important;
	  border-radius: 15px;
	  font-size: 10px;
	  padding: 5px;
	  float: right;
	}
	
	.cate_num_all {
	  display: inline-block;
	  background: #499E39;
	  border-radius: 50%;
	  position: absolute;
	  right: 8px;
	  width: 16px;
	  color: #fff;
	  top: 10px;
	  height: 16px;
	  line-height: 16px;
	  font-size: 10px;
	}
	
	.header_cate {
	  display: flex;
	  padding-top: 6vh;
	  background: #177B3D;
	  align-items: center;
	  padding-bottom: 5px;
	
	  text {
	    color: #fff;
	    font-size: 17px;
	    margin: 0 17px;
	  }
	
	  input {
	    background: #f7f7f7;
	    padding: 5px;
	    text-align: center;
	    border-radius: 16px;
	    font-size: 14px;
	    color: #969696;
	    width: 190px;
	  }
	}
	
	.category-wrap {
	  background-color: #fff;
	}
	
	.shop {
	  font-size: 15px;
	  margin-left: 7px;
	}

	.category-content {
	  overflow: hidden;
	}
	
	.cotegory-type {
	  width: 100%;
	}
	
	.category-tab {
	  width: 87px;
	  background: #f5f5f5;
	  overflow-y: scroll;
	  padding-bottom: 22px;
	
	  .seach {
	    padding: 20rpx 0;
	    font-size: 14px;
	    text-align: center;
	    color: #b6c0cf;
	  }
	
	  .seach .icon {
	    font-size: 25px !important;
	    display: block;
	  }
	
	  .item {
	    position: relative;
	    padding: 20px;
	    font-size: 16px;
	    text-align: center;
	    color: #6f6f6f;
	    display: inline-block;
	    text-align: center;
	    width: 100%;
	    box-sizing: border-box;
	  }
	
	  .item image {
	    width: 40px;
	    height: 40px;
	    margin: auto;
	    display: block;
	  }
	
	  .item.active {
	    position: relative;
	    background: #c9ebc9;
	    color: #000;
	    font-weight: bold;
	  }
	}
	
	.cotegory-type-3 .category-content {
	  flex: 1;
	  background-color: #e99494;
	}
	
	.scroll-3 {
	  height: 73vh;
	  margin: 0 10px;
	  padding-bottom: 15px;
	}
	
	.cotegory-type-3 .list {
	  padding: 0 25rpx;
	}
	
	.cotegory-type-3 {
	  display: flex;
	}
	
	.cotegory-type-3 .scroll-3 .item {
	  font-size: 24rpx;
	
	  .detail {
	    vertical-align: top;
	    width: 51%;
	    position: relative;
	    padding-top: 10px;
	  }
	
	  .cate_name {
	    width: 94%;
	    height: 91px;
	    border-radius: 10px;
	  }
	
	  .list_pro {
	    width: 94%;
	    background: #fff;
	    border-radius: 10px;
	    margin: 10px 0;
	    padding: 10px;
	    box-sizing: border-box;
	    display: flex;
	    justify-content: space-between;
	  }
	
	  .type-name {
	    font-size: 16px;
	    display: block;
	    -webkit-box-orient: vertical;
	    -webkit-line-clamp: 2;
	    overflow: hidden;
	    color: #343434;
	    font-weight: bold;
	  }
	
	  .selling_point {
	    display: block;
	    color: #999;
	    height: 100rpx;
	    overflow: hidden;
	    padding: 4px 0;
	    font-size: 12px;
	    line-height: 20px;
	  }
	
	  .price {
	    font-size: 18px;
	    color: #343434;
	    font-weight: 600;
	  }
	
	  .guige {
	    float: right;
	    padding: 0px 10px;
	    background-color: #278D44;
	    border-radius: 11px;
	    color: #fff;
	    z-index: 999;
	    font-size: 12px;
	    height: 22px;
	    line-height: 22px;
	  }
	}
	.cotegory-type-3 .scroll-3 .item .pro_img_info {
	  width: 45%;
	  height: 220rpx;
	  border-radius: 10px;
	}
	</style>

  • 5
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值