实现左右联动功能
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>分类</title>
<link rel="stylesheet" href="https://npm.webcache.cn/vant@3/lib/index.css" />
<script src="https://npm.webcache.cn/vue@3.5.25/dist/vue.global.js"></script>
<script src="https://npm.webcache.cn/vant@3/lib/vant.min.js"></script>
</head>
<body>
<div id="app">
<van-nav-bar title="测试" left-arrow fixed placeholder z-index="999" :safe-area-inset-top="true"
@click-left="onClickLeft"></van-nav-bar>
<div class="box-box">
<div class="left-nav" id="leftNav">
<div class="lf-lis" :class="{'selected':nagInd==index}" v-for="(category, index) in categories"
:key="index" @click="navigateToCategory(category.id,index)">
{{ category.name }}
</div>
</div>
<div class="right-content" id="right-content" ref="rightContent" @scroll="handleScroll">
<div v-for="(product, index) in products" :key="index" :id="'b'+index" class="ri-box">
<div class="ri-lis">
<div class="ri_lis-title">------{{ product.name }}------</div>
<div class="ri-lis-box">
<div class="ri-lis-li" v-for="(item, ind) in product.child" :key="ind">
<img class="imgs" :src="`https://develop.dongguanhongyun.com/resources/5903/202405/17168772712541156601615.png`" alt="" />
<div class="li_title">{{item.name}}</div>
</div>
</div>
</div>
</div>
<!-- 最后一类商品不够时,添加高度撑满屏幕 -->
<div class="entry-box" v-if="childLth<15"></div>
</div>
</div>
</div>
<script>
const app = Vue.createApp({
data() {
return {
categories: [
// 左侧导航栏的选项
{ id: 1, name: "分类1" },
{ id: 2, name: "分类2" },
{ id: 3, name: "分类3" },
],
nagInd: 0,
products: [
// 右侧商品列表的模块
{
id: "product1",
name: "商品1",
child: [
{ id: "product2", name: "商品1-1" },
{ id: "product2", name: "商品1-2" },
{ id: "product2", name: "商品1-3" },
{ id: "product4", name: "商品1-4" },
{ id: "product5", name: "商品1-5" },
],
},
{
id: "product2",
name: "商品2",
child: [
{ id: "product2", name: "商品1-1" },
{ id: "product2", name: "商品1-2" },
{ id: "product2", name: "商品1-3" },
],
},
{
id: "product3",
name: "商品3",
child: [
{ id: "product1", name: "商品1-1" },
{ id: "product2", name: "商品1-2" },
{ id: "product3", name: "商品1-3" },
{ id: "product4", name: "商品1-4" },
{ id: "product5", name: "商品1-5" },
{ id: "product6", name: "商品1-6" },
{ id: "product6", name: "商品1-7" },
],
},
// {
// id: "product4",
// name: "商品4",
// child: [
// { id: "product2", name: "商品1-1" },
// { id: "product2", name: "商品1-2" },
// { id: "product2", name: "商品1-3" },
// { id: "product4", name: "商品1-4" },
// ],
// },
],
childLth: "",
hightArr: [], //列表每个分类对应的区域top集合
dis_scroll: false,
};
},
created() { },
mounted() {
let that = this;
this.$nextTick(() => {
that.infoScroll();
});
const leftColumn = document.getElementById("leftNav");
const rightColumn = this.$refs.rightContent;
console.log("leftColumn -----> ", leftColumn);
console.log("rightColumn -----> ", rightColumn);
// 监听左侧按钮点击事件
leftColumn.addEventListener("click", function () {
that.dis_scroll = true;
});
// 监听右侧滚动事件
rightColumn.addEventListener("scroll", function (event) {
console.log("res1111111 -----> ", event);
// 获取右侧滚动距离
const scrolledElement = event.target;
const scrollDistance = scrolledElement.scrollTop;
// console.log("scrollDistance -----> ", scrollDistance);
if (!that.dis_scroll) {
console.log("右侧触发了滚动事件");
// 在这里添加处理右侧滚动事件的逻辑
// 设置左侧滚动位置-左右联动
// leftColumn.scrollTop = scrollDistance;
// 选中状态联动随之改变
// if (that.left_scroll) return;
that.hightArr.map((item, index) => {
if (scrollDistance > item) {
that.nagInd = index;
}
});
} else {
console.log("左侧触发了滚动事件");
that.dis_scroll = false;
}
});
},
methods: {
handleScroll() {
console.log(
"触底触底触底触底触底触底触底触底触底触底触底触底触底触底触底"
);
// 在这里处理触底事件的逻辑
},
navigateToCategory(categoryId, index) {
this.nagInd = index;
// console.log(
// "this.$refs.rightContent1111111 -----> ",
// this.$refs.rightContent.querySelector(`#b${index}`)
// );
// console.log(
// "this.$refs.rightContent3333333 -----> ",
// document.getElementById("right-content")
// );
// 找到对应分类在右侧商品列表中的位置
const categoryElement = this.$refs.rightContent.querySelector(
`#b${index}`
);
const rightEle = document.getElementById("right-content");
// const categoryElement = document.getElementById(`#b${index}`);//null
if (categoryElement) {
// 使用滚动或动画效果将页面滑动到对应位置
// categoryElement.scrollIntoView({ behavior: "smooth" }); //特别注意坑点-使用后左侧导航栏切换第一次切换有问题
rightEle.scrollTop = categoryElement.offsetTop - 44; //减去顶部导航栏高度
}
},
infoScroll: function () {
let that = this;
let len = that.products.length;
that.childLth = that.products[len - 1].child.length;
let height = 0;
let hightArr = [];
for (let i = 0; i < len; i++) {
//获取元素所在位置
let idView = "b" + i;
// console.log(" idView -----> ", idView);
let query = document.getElementById(idView);
// console.log(query, "queryqueryqueryquery");
let rect = query.getBoundingClientRect();
// console.log(rect, "rectrectrectrectrect");
let top = rect.top;
hightArr.push(top);
that.hightArr = hightArr;
// console.log(hightArr, "hightArrhightArr");
}
},
},
});
app.use(vant);
app.mount("#app");
</script>
<style>
body {
margin: 0;
padding: 0;
background-color: #f7f7f7;
}
.van-nav-bar .van-icon {
color: #000000;
}
.van-nav-bar__content {
background-color: #fff;
height: 44px;
}
.van-hairline--bottom:after {
border: none;
}
div {
box-sizing: border-box;
}
.box-box {
width: 100%;
height: calc(100vh - 44px);
display: flex;
}
.left-nav {
width: 100px;
height: 100%;
background-color: #fff;
overflow-y: auto;
}
.lf-lis {
width: 100%;
text-align: center;
height: 50px;
line-height: 50px;
}
.selected {
color: aqua;
}
.right-content {
flex: 1;
height: 100%;
overflow-y: auto;
}
.right-content::-webkit-scrollbar {
display: none;
}
.ri_lis-title {
width: 100%;
color: #999;
padding: 20px;
text-align: center;
}
.ri-lis-box {
width: 100%;
padding: 10px;
display: flex;
flex-wrap: wrap;
}
.ri-lis-li {
margin-right: 10px;
margin-bottom: 10px;
&:nth-child(3n) {
margin-right: 0;
}
}
.imgs {
width: 80px;
height: 80px;
border-radius: 50%;
}
.li_title {
width: 100%;
text-align: center;
font-size: 12px;
}
.entry-box {
height: calc(100vh - 100px);
}
</style>
</body>
</html>