现在有一个需求是实现多级动态菜单点击跳转到相应位置,一般这种需求实现起来就是href+id的方式锚点定位
但是这种方式的滚动很生硬,故不采纳
我使用的方案是根据id,获取到当前元素距离body顶部的距离,判断此时滚动条需要滚动的距离,再通过
window.scrollTo方法实现平滑滚动到该区域
具体实现方案:
1,定义菜单和内容区域,内容区域的id使用菜单首字母缩写
2,引入js-pinyin插件,识别当前点击菜单的首字母缩写,与内容区域id对应
3,获取内容区域距离body顶部的距离,由于元素offsetTop的计算是根据当前元素相对于最近的定位父元素计算出来的,
所以不能直接用“元素.offsetTop”获取,需要定义一个方法计算当前元素距离body顶部的“真实”距离。
4,通过window.scrollTo并开启平滑滚动
demo:
<template>
<div>
<!-- 菜单 -->
<div class="tabs">
<span v-for="(item,index) in tabList"
@click="toTabDetail(item)"
:key="index">{{ item.title }}</span>
</div>
<!-- 公司介绍 -->
<div class="tab_content"
id="gsjs">
<p>公司介绍</p>
</div>
<!-- 联系我们 -->
<div class="tab_content"
id="lxwm">
<p>联系我们</p>
</div>
<!-- 公司地址 -->
<div class="tab_content"
id="gsdz">
<p>公司地址</p>
</div>
</div>
</template>
<script>
import pinyin from 'js-pinyin'
pinyin.setOptions({ checkPolyphone: false, charCase: 1 }); // 1小写0大写,默认大写
export default {
data () {
return {
tabList: [
{
title: '公司介绍'
},
{
title: '联系我们'
},
{
title: '公司地址'
}
]
}
},
methods: {
toTabDetail ({ title }) {
const id = `#${pinyin.getCamelChars(title)}` // pinyin.getCamelChars获取字符串每个字首字母
this.$nextTick(() => {
window.scrollTo({
top: this.getOffsetTopByBody(document.querySelector(id)),
behavior: 'smooth' // 开启平滑滚动
})
})
},
// 获取元素相对于body的高度
getOffsetTopByBody (el) {
let offsetTop = 0
while (el && el.tagName !== 'BODY') {
offsetTop += el.offsetTop
el = el.offsetParent
}
return offsetTop
},
}
}
</script>
<style lang="scss" scoped>
.tabs {
display: flex;
justify-content: center;
margin: 100px 0;
span {
border: 1px solid red;
margin-right: 10px;
padding: 10px 20px;
cursor: pointer;
}
}
.tab_content {
width: 60vw;
height: 80vh;
border: 1px solid red;
margin: 10vh auto;
}
</style>