就是鼠标点击左边的栏目,右边的缓缓的定位到栏目,这种用什么做?有相应的插件还是手写js。
//之前遇到收藏了 你看看
<template>
<div id="linage">
<div>{{ currentOptions }}</div>
<div class="bottom">
<!-- 左侧菜单栏 -->
<div class="bottomLeft">
<div
class="leftItem"
v-for="(item0, index0) in leftArr"
:key="index0"
:class="{ highLight: whichIndex == index0 }"
@click="letItemHighLight(index0)"
ref="jiffje"
>
{{ item0 }}
</div>
</div>
<!-- 左侧菜单栏对应的右侧的内容 -->
<div class="bottomRight" ref="wrapper">
<div class="bottomRightContent" v-for="(item, index) in rightArr" :key="index" ref="item">
<div class="bottomRightContentHead">{{ item.titleOne }}</div>
<div class="bottomRightContentBody">
<el-col :span="8" v-for="(item2, index2) in item.titleTwo" :key="item2">
<span class="circle"></span>
<span class="word">{{ item2 }}</span>
</el-col>
<div style="clear: both"></div>
</div>
<div class="bottomRightContentFooter"></div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
whichIndex: 0, // 动态显示左侧菜单栏高亮
leftArr: [], // 左侧菜单栏的数据
rightArr: [], // 右侧详情展示对应的数据
rightHeightArr: [], // 右侧每一项的高度数组
rightHeightSumArr: [], // 右侧每一项的高度累加数组
r: 0, // 滚动的距离
currentOptions: "",
rightHeigh: [],
};
},
mounted() {
// 第一步,先发请求获取左右两侧的数据,用于渲染出页面,这里我们模拟一下发请求的数据
this.getLeftArrData();
this.getRightArrData();
},
methods: {
//左边栏数据
getLeftArrData() {
let apiLeftArr = [
"西游记",
"三国演义",
"红楼梦",
"水浒传",
"龙族",
"幻城",
"犬夜叉",
"海贼王",
"一拳超人",
"金刚狼",
"钢铁侠",
"灭霸",
"雷神",
"贪玩蓝月",
"梦幻西游",
"王者荣耀",
];
this.leftArr = apiLeftArr;
},
//右边栏数据
getRightArrData() {
let apiRightArr = [
{
titleOne: "西游记",
titleTwo: ["111", "222", "333", "444"],
},
{
titleOne: "三国演义",
titleTwo: ["111", "222"],
},
{
titleOne: "红楼梦",
titleTwo: ["111", "222", "333", "444", "111", "222", "333", "444"],
},
{
titleOne: "水浒传",
titleTwo: ["111", "222", "333", "444", "111", "222", "333", "444"],
},
{
titleOne: "龙族",
titleTwo: ["111", "222", "333", "444", "111", "222", "333", "444"],
},
{
titleOne: "幻城",
titleTwo: ["111", "222", "333", "444", "111", "222", "333", "444"],
},
{
titleOne: "犬夜叉",
titleTwo: ["111", "222", "333", "444", "111", "222", "333", "444"],
},
{
titleOne: "海贼王",
titleTwo: ["111", "222", "333", "444", "111", "222", "333", "444"],
},
{
titleOne: "一拳超人",
titleTwo: ["111", "222", "333", "444", "111", "222", "333", "444"],
},
{
titleOne: "金刚狼",
titleTwo: ["111", "222", "333", "444", "111", "222", "333", "444"],
},
{
titleOne: "钢铁侠",
titleTwo: ["111", "222", "333", "444", "111", "222", "333", "444"],
},
{
titleOne: "灭霸",
titleTwo: ["111", "222", "333", "444", "111", "222", "333", "444"],
},
{
titleOne: "雷神",
titleTwo: ["111", "222", "333", "444", "111", "222", "333", "444"],
},
{
titleOne: "贪玩蓝月",
titleTwo: ["111", "222", "333", "444", "111", "222", "333", "444"],
},
{
titleOne: "梦幻西游",
titleTwo: ["111", "222", "333", "444", "111", "222", "333", "444"],
},
{
titleOne: "王者荣耀",
titleTwo: [
"111",
"222",
"333",
"444",
"111",
"222",
"333",
"444",
"111",
"222",
"333",
"444",
"111",
"222",
"333",
"444",
"111",
"222",
"333",
"444",
"111",
"222",
"333",
"444",
"111",
"222",
"333",
"444",
"111",
"222",
"333",
"444",
"111",
"222",
"333",
"444",
"111",
"222",
"333",
"444",
"111",
"222",
"333",
"444",
"111",
"222",
"333",
"444",
"111",
"222",
"333",
"444",
"111",
"222",
"333",
"444",
"111",
"222",
"333",
"444",
"111",
"222",
"333",
"444",
],
},
];
this.rightArr = apiRightArr;
// 第二步,左右两侧有数据以后,才会把高度撑起来,才可以计算高度数组。注意先后顺序
// 使用this.$nextTick()将回调,也就是计算两个高度数组,延迟到下次 DOM 更新循环之后再计算
this.$nextTick(() => {
this.getTwoHeightArr();
});
},
getTwoHeightArr() {
//console.log("可能为空", this.$refs.item);
this.$refs.item.forEach((item) => {
this.rightHeightArr.push(item["offsetHeight"]);
});
let num = 0;
this.rightHeightArr.forEach((item) => {
num = num + item;
this.rightHeightSumArr.push(num);
});
// 第三步,有了高度滚动条以后,就可以绑定滚动事件了
this.bindScrollEvent();
},
bindScrollEvent() {
// 第四步,绑定滚动事件,看滚动到那个区间里面,思路就是通过右侧的区间去同步左侧的区间
this.$refs.wrapper.onscroll = () => {
this.r = this.$refs.wrapper.scrollTop;
// 看看浏览器滚动的高度落到那个区间,在那个区间,就让对应的项高亮
const scrollWhichIndex = this.rightHeightSumArr.findIndex((item, index) => {
return this.r >= this.rightHeightSumArr[index] && this.r < this.rightHeightSumArr[index + 1];
});
this.rightArr.forEach((v, i) => {
if (i - 1 == scrollWhichIndex) {
this.currentOptions = v.titleOne;
}
});
// 初始的区间为-1,所以还让其为第一项,即索引为0,当用户往下滑动的时候,所以就会
// 一直大于负一,所以就让其加上一和左侧的高亮项对应。
if (scrollWhichIndex > -1) {
this.whichIndex = scrollWhichIndex + 1;
} else {
this.whichIndex = 0;
}
};
},
// 第五步,当用户点击的时候再让其滚动,因为滚动和高亮是关联的,所以只要控制滚动,就相当于控制高亮。
// 滚动的距离就是,看用户点击的是哪个菜单项的索引,通过索引找到累加数组对应的那一项,
// 也就是滚动的距离。当为第一项的时候边界值要控制一下
letItemHighLight(i) {
if (this.rightHeightSumArr[i - 1] == undefined) {
this.$refs.wrapper.scrollTop = 0;
} else {
this.$refs.wrapper.scrollTop = this.rightHeightSumArr[i - 1];
}
},
},
};
</script>
<style lang="less" scoped>
.top {
width: 100%;
height: 80px;
text-align: center;
line-height: 80px;
background-color: #e9e9e9;
}
.bottom {
width: 100%;
height: calc(100% - 80px);
display: flex;
.bottomLeft {
width: 288px;
height: 100%;
background-color: #eee;
.leftItem {
width: 100%;
height: 50px;
line-height: 50px;
text-align: center;
cursor: pointer;
}
.leftItem:hover {
background-color: #dfe3f1;
}
.highLight {
background: #dfe3f1;
}
}
.bottomRight {
width: calc(100% - 288px);
height: 100%;
box-sizing: border-box;
padding: 14px 36px 0 36px;
overflow-y: auto;
.bottomRightContent {
width: 100%;
box-sizing: border-box;
padding-bottom: 36px;
.bottomRightContentHead {
height: 25px;
font-family: PingFang SC;
font-style: normal;
font-weight: 600;
font-size: 24px;
line-height: 25px;
text-transform: capitalize;
color: rgba(0, 0, 0, 0.85);
margin-bottom: 32px;
}
.bottomRightContentBody {
.el-col {
position: relative;
margin-bottom: 18px;
.circle {
display: inline-block;
width: 6px;
height: 6px;
background: #4677f6;
border-radius: 50%;
position: absolute;
top: 8px;
left: 0;
}
.word {
margin-left: 12px;
font-family: PingFang SC;
font-style: normal;
font-weight: normal;
font-size: 14px;
color: #4677f6;
cursor: pointer;
}
.word:hover {
text-decoration: underline;
}
.topPlace {
position: absolute;
top: 1px;
margin-left: 8px;
}
}
}
.bottomRightContentFooter {
height: 1px;
width: 100%;
margin-top: 14px;
background-color: #e9e9e9;
}
}
}
}
</style>
可以了解一下scrollIntoView
这个文章里的案例和你的功能类似https://zhuanlan.zhihu.com/p/525742938?utm_id=0
一个想法,没具体实验过,通过锚点的 CSS 属性 :target
触发一个 transition
的过渡效果,比如
a#test:target {
transition: all 200ms linear;
}
只是一个猜想,行不行不知道
8 回答4.7k 阅读✓ 已解决
6 回答3.4k 阅读✓ 已解决
5 回答2.8k 阅读✓ 已解决
5 回答6.3k 阅读✓ 已解决
4 回答2.3k 阅读✓ 已解决
5 回答1.3k 阅读✓ 已解决
4 回答2.8k 阅读✓ 已解决
scrollIntoView
,楼上说过了参考:
对页面或者容器父元素设置:
scroll-behavior: smooth;
实现内容的平滑移动。使用 JS 处理。
scrollTo()