重新实现分类组件逻辑

This commit is contained in:
TOP糯米 2023-03-09 01:40:16 +08:00
parent 35b5535a97
commit d39cc6a2fb
1 changed files with 87 additions and 154 deletions

View File

@ -1,20 +1,13 @@
<template>
<view class="component-cate" :style="{ height: wrapHeight + 'px' }">
<view class="menu-wrap">
<scroll-view
scroll-y
class="tab-view menu-scroll-view"
:scroll-top="scrollTop"
:scroll-into-view="itemId"
:enhanced="true"
:bounces="false"
>
<scroll-view scroll-y class="tab-view menu-scroll-view" :scroll-top="scrollLeftTop" :enhanced="true" :bounces="false">
<view
class="tab-item"
v-for="(item, index) in data"
:key="index"
:class="[current == index ? 'tab-item-active' : '']"
@tap.stop="swichMenu(index)"
:class="[currentLeftIndex == index ? 'tab-item-active' : '']"
@tap.stop="switchMenu(index)"
>
<text class="line-1">{{ item.name }}</text>
</view>
@ -32,9 +25,8 @@
<view
class="class-item"
v-for="(item, index) in data"
:id="'item' + index"
:key="index"
:style="{ height: index == data.length - 1 ? wrapHeight + utils.rpx2px(110) + 'px' : 'auto' }"
:style="{ height: index == data.length - 1 ? wrapHeight + 'px' : 'auto' }"
>
<cate-tmpl v-if="cateType === 'cate'" :parentId="item.id" :data="item" @clickItem="clickItem"></cate-tmpl>
<list-tmpl v-if="cateType === 'list'" :parentId="item.id" :data="item" @clickItem="clickItem"></list-tmpl>
@ -53,18 +45,16 @@ export default {
data() {
return {
utils: this.$utils,
scrollTop: 0, //tab
oldScrollTop: 0, // tab
current: 0, //
menuHeight: 0, //
menuItemHeight: 50, // item
itemId: "", // scroll-viewid
arr: [], //
scrollRightTop: 0, // scroll-view
isReady: false,
leftNodePos: [],
rightNodePos: [],
queryTimer: null,
currentLeftIndex: 0,
wrapHeight: 0,
// ID
timer: null,
activeIndex: 0,
scrollLeftTop: 0,
scrollRightTop: 0,
menuHeight: 0,
};
},
props: {
@ -91,7 +81,6 @@ export default {
},
created() {},
mounted() {
this.getMenuItemTop();
const { windowHeight, statusBarHeight, headerHeight } = getApp().globalData.pageConfig;
// ------------------------------------------
// #ifndef H5
@ -108,163 +97,107 @@ export default {
// H5tabbar
this.wrapHeight -= this.$utils.rpx2px(100);
// #endif
this.menuHeight = this.$utils.rpx2px(100);
},
destroyed() {},
watch: {
/**
* 监听列表数据变化
*/
data() {
this.init().then(() => {
this.isReady = true;
this.reAction();
});
},
/**
* 监听ID变化
*/
activeId() {
if (this.isReady) {
this.reAction();
}
},
},
methods: {
getElRect(elClass, dataVal) {
new Promise((resolve, reject) => {
const query = uni.createSelectorQuery().in(this);
query
.select("." + elClass)
.fields(
{
size: true,
},
(res) => {
// resnull
if (!res) {
// this.getElRect(elClass);
return;
/**
* 执行具体逻辑
*/
reAction() {
this.switchCate(this.activeId);
},
/**
* 初始化列表
*/
init() {
clearTimeout(this.queryTimer);
return new Promise((resolve, reject) => {
const that = this;
this.queryTimer = setTimeout(() => {
that.rightNodePos = [];
let query = uni.createSelectorQuery().in(that);
query
.selectAll(".class-item")
.boundingClientRect((result) => {
if (result.length > 0) {
result.forEach((item) => {
that.rightNodePos.push(item.top - result[0].top);
});
resolve();
}
this[dataVal] = res.height;
resolve();
}
)
.exec();
})
.exec();
}, 200);
});
},
/**
* 获取右边菜单每个item到顶部的距离
* 储存到 arr 数组里面用于后面滚动判断
* 更新左侧菜单
*/
getMenuItemTop() {
new Promise((resolve) => {
let selectorQuery = uni.createSelectorQuery().in(this);
selectorQuery
.selectAll(".class-item")
.boundingClientRect((rects) => {
// rects[](selectAll)
if (!rects.length) {
// this.getMenuItemTop();
return;
}
rects.forEach((rect) => {
// rects[0].top()
this.arr.push(rect.top - rects[0].top);
// this.arr.push(rect.top)
resolve();
});
})
.exec();
});
updateMenuStatus(index) {
this.currentLeftIndex = index;
this.scrollLeftTop = index * this.menuHeight - this.wrapHeight / 2;
},
/**
* 观测元素相交状态
* 检测右边scroll-view的id为itemxx的元素与right-box的相交状态
* 如果跟.right-box底部相交就动态设置左边栏目的活动状态
* 滚动监听
*/
async observer() {
this.data.map((val, index) => {
let observer = uni.createIntersectionObserver(this);
observer
.relativeTo(".right-box", {
top: 0,
})
.observe("#item" + index, (res) => {
if (res.intersectionRatio > 0) {
let id = res.id.substring(4);
this.leftMenuStatus(id);
}
});
});
},
/**
* 设置左边菜单的滚动状态
* @index 传入的 ID
*/
async leftMenuStatus(index) {
this.current = index;
// 0
if (this.menuHeight == 0 || this.menuItemHeight == 0) {
await this.getElRect("menu-scroll-view", "menuHeight");
await this.getElRect("component-tab-item", "menuItemHeight");
}
// item
this.scrollTop = index * this.menuItemHeight + this.menuItemHeight / 2 - this.menuHeight / 2;
},
/**
* 点击左边的栏目切换
* @index 传入的 ID
*/
async swichMenu(index) {
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.leftMenuStatus(index);
});
},
/**
* 右边菜单滚动
* 如果不存在height2意味着数据循环已经到了最后一个设置左边菜单为最后一项即可
*/
async rightScroll(e) {
this.oldScrollTop = e.detail.scrollTop;
if (this.arr.length == 0) {
await this.getMenuItemTop();
}
if (!this.menuHeight) {
await this.getElRect("menu-scroll-view", "menuHeight");
}
// scrollHeight
// let scrollHeight = e.detail.scrollTop + this.menuHeight / 2;
// scrollHeight
let scrollHeight = e.detail.scrollTop + 15;
for (let i = 0; i < this.arr.length; i++) {
let height1 = this.arr[i];
let height2 = this.arr[i + 1];
if (!height2 || (scrollHeight >= height1 && scrollHeight < height2)) {
this.leftMenuStatus(i);
rightScroll(e) {
let scrollTop = e.detail.scrollTop + 15;
for (let index = 0; index < this.rightNodePos.length; index++) {
let current = this.rightNodePos[index];
let next = this.rightNodePos[index + 1];
if (!next || (scrollTop >= current && scrollTop < next)) {
this.updateMenuStatus(index);
return;
}
}
},
/**
* 选中某项
*/
switchMenu(index) {
this.currentLeftIndex = index;
this.scrollRightTop = this.rightNodePos[index];
},
/**
* 按ID选中
*/
async switchCate(id) {
if (this.arr.length == 0) {
await this.getMenuItemTop();
}
switchCate(id) {
let activeIndex = 0;
this.data.forEach((item, index) => {
if (item.id == id) {
this.activeIndex = index;
activeIndex = index;
}
});
this.swichMenu(this.activeIndex);
this.switchMenu(activeIndex);
},
/**
* 点击
*/
clickItem(parentId, id) {
this.$emit("clickItem", parentId, id);
},
},
watch: {
activeId(activeId) {
this.switchCate(activeId);
},
arr(arr) {
clearTimeout(this.timer);
if (this.activeIndex > 0) {
const that = this;
this.timer = setTimeout(() => {
that.scrollRightTop = arr[that.activeIndex];
}, 200);
}
},
},
};
</script>