<template> <view class="clearfix" :class="['qn-page-' + theme]"> <view class="float_left"> <scroll-view scroll-y class="left-aside" :style="{ height: 'calc(100vh - 112rpx - ' + (isBang ? '84px' : '50px') + ')' }"> <view v-for="item in cate_list" :key="item.id" class="f-item b-b ellipsis" :class="{ active: item.id === current_item.id }" @click="tabtap(item)"> <view v-if="item.id === current_item.id" class="active-line primary-bg"></view> {{ item.title }} </view> </scroll-view> </view> <view class="float_right"> <!-- 二级下拉菜单 --> <view class="two-cate"> <scroll-view :scroll-x="true" scroll-with-animation class="two-cate-scroll" :scroll-left="two_cate_scroll"> <view v-for="(item, index) in current_item.children" :key="index" :class="[tow_current === index ? 'primary-btn-pain' : '']" class="cate-two-li" @click="twoCateChange(index, item)" > {{ item.title }} </view> </scroll-view> </view> <scroll-view scroll-y scroll-with-animation class="right-aside" :style="{ height: 'calc(100vh - 188rpx - ' + (isBang ? '84px' : '50px') + ')' }" :scroll-top="scroll_right_top" @scroll="rightScroll" > <view v-for="(titem, tindex) in current_item.children" :key="tindex" class="cate-ul" :id="'item' + tindex"> <block v-if="titem.children.length"> <view class="cate-name">{{ titem.title }}</view> <view class="clearfix"> <view class="cate-li" v-for="(item, index) in titem.children" :key="index" @click="goPage('/pagesT/productDetail/productDetail?id=' + item.id + '&name=' + item.title)" > <view class="cate-img-view"> <image v-if="item.images" :src="item.images" mode="aspectFill" class="cate-img"></image> <view class="ibonfont ibonleimupinleifenleileibie cate-img-icon" v-else></view> </view> <view class="cate-tit ellipsis">{{ item.title }}</view> </view> </view> </block> </view> </scroll-view> </view> </view> </template> <script> export default { data() { return { cate_list: [], tow_current: 0, current_item: {}, scroll_right_top: 0, // 右边三级分类栏目scroll-view的滚动条高度 old_scroll_top: 0, option_arr: [], // 把3级分类的每一块位置信息存储到数组中 two_cate_scroll: 0, // 2级分类滚动 menu_width: 0, // 2级分类菜单的宽度 menu_item_width: 0, // 2级分类菜单item的宽度 timer: null, // 定时器 menu_height: 0 // 3级菜单高度 }; }, computed: { isBang() { return this.$_utils.modelmes(); }, userId() { return this.$store.state.userStatus.id; } }, created() { this.getAllCategory(); }, methods: { // 分类列表 getAllCategory getAllCategory() { this.$u.api .getAllCategory({ userCenterId: this.userId || 0 }) .then(({ data }) => { this.cate_list = data; if (data.length) { this.current_item = data[0]; } this.getMenuItemTop(); }); }, // 一级分类切换 tabtap(row) { this.current_item = row; this.tow_current = 0; }, // 2级分类切换 async twoCateChange(index, row) { if (this.option_arr.length == 0) { await this.getMenuItemTop(); } if (row.id == this.two_id) return; this.scroll_right_top = this.old_scroll_top; this.$nextTick(() => { this.scroll_right_top = this.option_arr[index]; this.tow_current = index; this.twoMenuStatus(index, 1); }); }, // 3级分类列表滚动 async rightScroll(e) { this.old_scroll_top = e.detail.scrollTop; // if(this.option_arr.length == 0) { // await this.getMenuItemTop(); // } // if(this.timer) return ; // if(!this.menu_height) { // await this.getElRect('right-aside', 'menu_height','height'); // } // setTimeout(() => { // 节流 // this.timer = null; // // scrollHeight为右边菜单垂直中点位置 // let scrollHeight = e.detail.scrollTop + this.menu_height / 2; // for (let i = 0; i < this.option_arr.length; i++) { // let height1 = this.option_arr[i]; // let height2 = this.option_arr[i + 1]; // // 如果不存在height2,意味着数据循环已经到了最后一个,设置2级菜单为最后一项即可 // if (!height2 || scrollHeight >= height1 && scrollHeight < height2) { // this.twoMenuStatus(i); // return ; // } // } // }, 10) }, // 设置2级分类的滚动状态 async twoMenuStatus(index) { this.tow_current = index; // 如果为0,意味着尚未初始化 if (this.menu_width == 0 || this.menu_item_width == 0) { await this.getElRect('two-cate-scroll', 'menu_width', 'width'); await this.getElRect('cate-two-li', 'menu_item_width', 'width'); } // 将菜单活动item居中 this.two_cate_scroll = index * this.menu_width + this.menu_item_width / 2 - this.menu_width / 2; }, // 获取3级分类列表菜单每个item到顶部的距离 getMenuItemTop() { new Promise(resolve => { let selectorQuery = uni.createSelectorQuery().in(this); //添加节点的布局位置的查询请求 selectorQuery .selectAll('.cate-ul') .boundingClientRect(rects => { // 如果节点尚未生成,rects值为[](因为用selectAll,所以返回的是数组),循环调用执行 if (!rects.length) { setTimeout(() => { this.getMenuItemTop(); }, 10); return; } rects.forEach(rect => { // 这里减去rects[0].top,是因为第一项顶部可能不是贴到导航栏(比如有个搜索框的情况) this.option_arr.push(rect.top - rects[0].top); resolve(); }); }) .exec(); }); }, // 获取一个目标元素的宽度 getElRect(elClass, dataVal, option) { 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, dataVal); }, 10); return; } this[dataVal] = res[option]; resolve(); } ) .exec(); }); } } }; </script> <style lang="scss"> .left-aside { width: 200upx; background-color: #f5f6f7; /* #ifdef H5||MP */ height: calc(100vh - 130upx); /*#endif*/ /* #ifdef APP-PLUS */ height: 100vh; /*#endif*/ .f-item { -webkit-line-clamp: 1; width: 100%; height: 80upx; line-height: 80rpx; padding-left: 48rpx; margin-bottom: 10rpx; font-size: 26upx; color: #4b4b4b; position: relative; &.active { color: #000000; font-size: 32upx; font-weight: bold; background-color: #ffffff; border-radius: 100rpx 0 0 100rpx; } .active-line { position: absolute; left: 28rpx; top: 50%; transform: translateY(-50%); height: 24upx; width: 4upx; border-radius: 4rpx; } } } .two-cate { .two-cate-scroll { width: 550upx; padding: 14rpx 0; white-space: nowrap; .cate-two-li { padding: 0 32rpx; display: inline-block; font-size: 24rpx; margin-left: 16rpx; border: 1px solid #f5f6f7; background-color: #f5f6f7; border-radius: 50rpx; height: 48rpx; line-height: 48rpx; &:last-child { margin-right: 40rpx; } &:first-child { margin-left: 40rpx; } } } } .right-aside { /* #ifdef H5||MP */ height: calc(100vh - 140upx); /*#endif*/ /* #ifdef APP-PLUS */ height: 100vh; /*#endif*/ width: 550upx; .cate-name { padding-top: 20rpx; padding-left: 40rpx; font-size: 26rpx; font-weight: 600; color: #000000; } .cate-li { float: left; width: 130upx; text-align: center; margin: 20upx 0 20rpx 40rpx; .cate-img-view { width: 130rpx; height: 104rpx; background: #f5f7f7; border-radius: 8px; margin-bottom: 24rpx; .cate-img { width: 84upx; height: 84upx; border-radius: 8upx; display: block; margin: 0 auto; transform: translateY(10rpx); } .cate-img-icon { font-size: 80upx; width: 84upx; line-height: 84upx; color: #eeeeee; height: 84upx; border-radius: 8upx; margin: 0 auto; transform: translateY(10rpx); } } .cate-tit { font-size: 24upx; font-weight: 400; color: #3a3a3a; width: 100%; -webkit-line-clamp: 1; } } } </style>