工作中遇到一个左右菜单联动的需求,记录一下。
如图
主要的实现功能
1.点击左侧右侧滚动到对应位置
2.右侧滑动,左侧对应图标选中
- 滚动到相应位置
document.getElementById('item' + item.appTypeName).scrollIntoView({
block: 'start',
behavior: 'smooth'
})
2.我的思路是检测所有可见范围的item是否可见,其中index最小的就是左侧应该显示index.
检查可见item
getBoundingClientRect 是元素距离可见试图做左上角的距离
checkVisible(elm) {
var rect = elm.getBoundingClientRect();
//获取当前浏览器的视口高度,不包括工具栏和滚动条
//document.documentElement.clientHeight兼容 Internet Explorer 8、7、6、5
var viewHeight=Math.max(document.documentElement.clientHeight,window.innerHeight);
//bottom top是相对于视口的左上角位置
//bottom大于0或者top-视口高度小于0可见
return !(rect.bottom < 70 || rect.top - viewHeight >= 0);
},
这边会有一个问题scroll事件会频繁触发,导致右侧菜单在滚动时左侧每一个都会亮一次,比如右侧从2滑动到5,2345都会一次亮一次,所以我做了一下防抖,
onScroll(e) {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
this.scorlling = false
this.$nextTick(() => {
let count = []
this.tabDataList.forEach((item, index) => {
//查找可见item
if (this.checkVisible(document.getElementById('item' + item.appTypeName))) {
count.push(index)
}
})
//找出最小的
let index = Math.min(...count)
if (this.selecting) {
return
} else {
this.selectName = this.tabDataList[index].appTypeName
}
})
}, 100)
},
下面是布局文件
因为是移动端的,使用了uniapp和vant,可以根据自己的项目更改
<view class="fun-body" @touchmove.stop @touch.stop>
<view class="left-content">
<view v-for="(item,index) in tabDataList"
:class="selectName==item.appTypeName?['left-item','left-item-select']:['left-item']"
@click="selectIndex(item)" :href="'#item.appTypeName'">
<view :class="selectName==item.appTypeName?['slect-blue']:['slect-gray']"></view><span
style="margin-left: 18rpx;"
:class="selectName==item.appTypeName?['slect-blue-text']:['slect-gray-text']">{{item.appTypeName}}</span>
</view>
</view>
<view class="right-content" @touchmove.stop @touch.stop @scroll.passive="onScroll">
<view v-for="item in tabDataList" class="right-item" :id="'item' + item.appTypeName">
<view class="item-title">
{{item.appTypeName}}
</view>
<u-grid :border="false">
<u-grid-item v-for="childrenItem in item.appSysMenuVoList" class="gr-item"
@click="toDetail(childrenItem)">
<view :class="['icon', childrenItem.appIcon ,'icon-width']"></view>
<view class="bottom-center-text">
{{childrenItem.appMenuName}}
</view>
</u-grid-item>
</u-grid>
<view style="background-color:#EBEDF0 ;margin-bottom: 16rpx;height: 15rpx;"></view>
</view>
<view style="height: 1330rpx;"></view>
</view>
</view>
2023/07/06
最近写视屏懒加载发现另一种判断是否在可视区域的方法记录一下
IntersectionObserver是一个可以判断是否在可视区域的方法,不过也需要做好节流
const intersectionObserver = new IntersectionObserver((entries) => {
// 如果 intersectionRatio 为 0,则目标在视野外,
entries.forEach((entry) => {
if (entry.intersectionRatio > 0) {
// console.log("在视野范围", entry.target.id);
} else {
// console.log("不在视野范围", entry.target.id);
}
});
});
onMounted(() => {
// 开始监听
intersectionObserver.observe(
document.getElementById(`${props.data.id}`) as any
);
});