> **<template>
<div>
<div class="nmc-content">
<div class="nmc-wrapper">
<div class="left" ref="scrollLeft">
<div v-for="(item, index) in arr" :key="index" ref='leftBox' @click="changeModel(index)"
:class="[current==index?'active flex-one':'common flex-one']">
{{item.name}}
</div>
</div>
<div class="right" ref="scroll" @scroll="handleScroll">
<div class="main-content" v-for="(item, index) in arr" :key="index">
<div class="top-title" ref="rightTit">{{item.name}}</div>
<div class="bottom-content">
<ul class="bottom-ul" v-if="item.list">
<li class="bottom-item" v-for="(item1, index1) in item.list" :key="index1">
<img src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fitem%2F202103%2F09%2F20210309094501_jfyix.thumb.1000_0.jpg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1675911945&t=14dcf3ffd9b9884f4accc0941ed6f140"
alt="" />
<div>{{item1.name}}</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<TabBar></TabBar>
</div>
</template>
<script>
import TabBar from '../components/TabBar.vue'
export default {
data() {
return {
leftClickFlag: false,
arr: [{
name: "分类1",
list: [{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
],
},
{
name: "分类2",
list: [{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
],
},
{
name: "分类3",
list: [{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
],
},
{
name: "分类4",
list: [{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
],
},
{
name: "分类5",
list: [{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
],
},
{
name: "分类6",
list: [{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
],
},
{
name: "分类7",
list: [{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
],
},
{
name: "分类8",
list: [{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
],
},
{
name: "分类9",
list: [{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
],
},
{
name: "分类10",
list: [{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
],
},
{
name: "分类11",
list: [{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
{
name: "二级"
},
],
},
],
current: 0,
listHeight: [],
scrollY: 0,
};
},
components: {
TabBar
},
mounted() {
this.$nextTick(() => {
this.getBoxHeight();
this.current = 0;
this.changeModel(0);
});
},
methods: {
getBoxHeight() {
setTimeout(() => {
//延时计算元素的宽度
let rightItems =
this.$refs.scroll.getElementsByClassName("main-content"); //获取指定类名的所有元素
let height = 0;
this.listHeight.push(height);
for (let i = 0; i < rightItems.length; i++) {
let item = rightItems[i]; // 右边的每一个模块(蓝色标题 + 标题下面所带的内容)
height += item.clientHeight;
this.listHeight.push(height); // 把右边模块内容的高度全都放到一个数组中
}
this.arr.forEach((item, index) => {
// 把上面弄的那些高度分别放入总数据中,方便点击左边让右边滚动到所对应的模块
this.$set(item, "distance", this.listHeight[index]);
// this.$set
// 向响应式对象中添加一个属性,
// 并确保这个新属性同样是响应式的,
// 且触发视图更新。
// 它必须用于向响应式对象上添加新属性
// 调用方法:this.$set( target, key, value )
// target:要更改的数据源(可以是对象或者数组)
// key:要更改的具体数据
// value :重新赋的值
});
}, 1000); //增加延时,等图片渲染完毕后进行计算
},
changeModel(index) {
if (index == 0) {
this.$refs.scroll.scrollTop = 0;
} else {
this.$refs.scroll.scrollTop = this.arr[index].distance;
}
this.current = index;
let jumpitem = this.$refs.scroll.getElementsByClassName("main-content")
jumpitem[index].scrollIntoView({
behavior: 'smooth',
block: 'start'
})
this.leftClickFlag = true;
},
// 左侧滚动
handleScrollLeft() {
let leftHeight = this.$refs.leftBox[0].clientHeight;
let height = (this.current - 6) * leftHeight;
if (this.current > 6) {
this.$refs.scrollTop += height;
}
if (this.current <= 6) {
this.$refs.scrollTop = 0;
}
},
// 滚动时触发
handleScroll() {
this.scrollY = this.$refs.scroll.scrollTop; // 先获取滚动元素的scrollTop,主要用它来进行判断
if (this.scrollY < this.arr[1].distance) {
this.current = 0;
} else {
for (let i = 0; i < this.listHeight.length; i++) {
let start = this.listHeight[i + 1]; // 右边模块内容的高度
let end = this.listHeight[i + 2]; // 右边模块内容的高度 加上 右边模块标题的高度
if (this.scrollY >= start && this.scrollY < end) {
if (this.leftClickFlag == false) {
//如果右侧数据过少,不触发右侧滚动
this.current = i + 1;
}
if (this.leftClickFlag) {
//设置完之后立马重置,右侧滚动触发左侧
this.leftClickFlag = false;
}
this.handleScrollLeft();
return;
}
}
}
},
},
};
</script>
<style lang='scss' scoped>
.flex-one {
display: flex;
justify-content: center;
align-content: center;
}
.nmc-content {
background: #f4f5f6;
padding: 0.6rem 0 0 0;
.nmc-wrapper {
width: 100%;
height: calc(100vh - 0.6rem);
display: flex;
.left {
width: 4.5rem;
// height: 100%;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
color: #333333;
&::-webkit-scrollbar {
display: none;
/* Chrome Safari */
}
>div {
font-size: 0.7rem;
font-weight: 500;
width: 4.5rem;
height: 2.5rem;
position: relative;
.top {
position: absolute;
top: -0.5rem;
right: 0;
width: 0.5rem;
height: 0.5rem;
background: white;
}
.bottom {
position: absolute;
top: 2.5rem;
right: 0;
width: 0.5rem;
height: 0.5rem;
background: white;
}
}
.active {
background: #ffffff;
background: white;
color: #333333;
display: flex;
align-items: center;
border-radius: 0;
&::before {
width: 0.25rem;
height: 1.55rem;
background: #363636;
content: '';
position: absolute;
top: 0.55rem;
left: 0;
}
.line {
width: 0.15rem;
height: 0.75rem;
object-fit: cover;
margin: 0 0.5rem 0 0;
}
}
.common {
color: #666666;
line-height: 2.5rem;
}
}
.right {
background: white;
position: relative;
flex: 1;
width: 100%;
height: 100%;
background: #fff;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
padding: 0.5rem;
.main-content {
position: relative;
width: 100%;
.top-title {
height: 2rem;
text-align: left;
line-height: 2rem;
font-size: 0.65rem;
font-weight: 500;
color: #333333;
}
.bottom-content {
// display: flex;
// flex-wrap: wrap;
// min-height: 17rem;
// margin: 0 0.5rem;
.bottom-ul {
width: 100%;
display: flex;
flex-wrap: wrap;
.bottom-item {
width: 33.33%;
// height: 5rem;
display: flex;
flex-direction: column;
align-items: center;
margin: 0 0 0.5rem 0;
position: relative;
>img:first-child {
width: 2.5rem;
height: 2.5rem;
// border: 0.025rem solid #f2f2f2;
border-radius: 0.25rem;
object-fit: cover;
box-shadow: 0rem 0.08rem 0.15rem 0.08rem rgba(194, 146, 108, 0.1);
}
}
}
}
}
}
}
}
</style>**
vue左右联动
于 2023-04-06 17:35:09 首次发布