vue+vant实现浮动导航栏点击定位到模块,且选中效果随滚动切换
1.主页面中导入浮动导航栏(使用vant的粘性布局sticky组件,使首屏下方的导航栏随页面滚动浮动在想要的位置):
<template>
<div class="app-container">
<!-- 浮动导航 -->
<van-sticky
style="
z-index: 1;
position: absolute;
top: 12.34rem;
left: 0;
width: 100%;
height: 0.76rem;
"
offset-top="0.95rem"
>
<tabs-index />
</van-sticky>
<top-index @login="toLogin" @bind="toBindRole" />
// 这里省略页面的主要内容(即浮动栏可切换的模块内容)
<foot-index />
<login-index ref="login" />
<bind-index ref="bind" />
</div>
</template>
<script>
import store from "@/store";
import { mapGetters, mapActions } from "vuex";
import TabsIndex from "@/components/TheTabs/TabsIndex";
import TopIndex from "@/components/TheTop/TopIndex";
import LoginIndex from "@/components/TheLogin/LoginIndex";
import BindIndex from "@/components/TheBindRule/BindIndex";
import FootIndex from "@/components/TheFoot/FootIndex";
export default {
name: "App",
components: {
TopIndex,
LoginIndex,
TabsIndex,
BindIndex,
FootIndex,
},
computed: {
...mapGetters(["token", "roleId"]),
},
mounted() {
},
methods: {
...mapActions([
"setUser",
"setPhone",
]),
},
};
</script>
2.导航栏代码:
<!-- tabs -->
<template>
<aside>
<div :class="$style.wrap" :style="{ ...otherStyle }">
<ul :class="$style.tabs">
<li
v-for="(el, index) in tabList"
:key="index"
:class="[
$style.li,
activeKey === el.value ? $style.active : '',
index === 1 && creativeInfo.status && creativeInfo.status === 1
? $style.entries
: '',
]"
@click="checkTab(el.value, index)"
>
<div
:class="[$style.itemText]"
:style="{
backgroundPosition:
index === 3 && creativeInfo.vote_status === 2
? `${-(0.93 * 4)}rem 0`
: `${-(0.93 * index)}rem 0`,
}"
></div>
</li>
</ul>
</div>
</aside>
</template>
<script>
import { mapGetters, mapActions } from "vuex";
export default {
name: "TabsIndex",
components: {},
props: {
otherStyle: {
type: Object,
default() {
return {};
},
},
},
data() {
return {
tabList: [{ value: "1" }, { value: "2" }, { value: "3" }, { value: "4" }],
activeKey: "1"
};
},
computed: {
...mapGetters(["roleGifts", "creativeInfo"]),
},
mounted() {
window.addEventListener("scroll", this.onScroll);
},
destroyed() {
window.removeEventListener("scroll", this.onScroll);
},
methods: {
...mapActions(["setLikeData"]),
pxToRem(num) {
const { clientWidth } = document.body;
if (clientWidth >= 750) {
return num;
}
return num * (clientWidth / 750);
},
// 点击tab
checkTab(bind_id) {
this.activeKey = bind_id;
const TARGET = {
"1": "first",
"2": "second",
"3": "third",
"4": "four",
};
if (bind_id) {
const targetObj = document.querySelector(`#j-${TARGET[bind_id]}`);
if (targetObj) {
const { offsetTop } = targetObj;
const scrollTop = offsetTop - this.pxToRem(0);
document.body.scrollTop = scrollTop;
document.documentElement.scrollTop = scrollTop;
}
}
},
onScroll(){
// 获取所有锚点元素
const targetObj = document.querySelectorAll(`.tabContent`);
// 获取所有锚点元素的offsetTop
const offsetTopArr = [];
targetObj.forEach(item => {
offsetTopArr.push(item.offsetTop);
});
// 获取当前文档流的 scrollTop
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
// 定义当前点亮的导航下标
let navIndex = 0;
for (let n = 0; n < offsetTopArr.length; n++) {
// 如果scrollTop大于等于第n个元素的ofssetTop,则说明第n-1个元素的内容完全不可见,此时导航索引就是n
if (scrollTop >= offsetTopArr[n]) {
navIndex = n;
}
}
this.activeKey = String(navIndex + 1);
}
},
};
</script>
<style lang="less" module>
.wrap {
width: 100%;
height: 0.76rem;
display: flex;
justify-content: center;
> div:first-child {
height: 100%;
}
}
.li {
position: relative;
width: 23%;
height: 0.5rem;
text-align: center;
line-height: 1;
display: flex;
justify-content: center;
align-items: center;
margin: 0 1%;
}
.itemText {
.size(0.92rem, 0.24rem);
.background-fill("./images/tab_title.png", 500% 100%);
}
.active {
background-color: #d9c9c5;
}
.entries {
position: relative;
&::after {
content: "";
position: absolute;
top: 0;
right: 0;
width: 0.25rem;
height: 0.25rem;
.background-fill("./images/tab_new.png");
}
}
.tabs {
width: 6.52rem;
height: 0.76rem;
.background-fill("./images/tab_bg.png");
display: flex;
justify-content: space-between;
padding: 0.12rem 0.32rem;
box-sizing: border-box;
> li {
&::before {
content: "|";
position: absolute;
left: 102%;
bottom: 0;
top: 0.14rem;
color: #6a4a19;
font-size: 0.2rem;
pointer-events: none;
}
}
> li:last-child {
&::before {
display: none;
}
}
}
</style>
那么这个功能就这么做完了。

浙公网安备 33010602011771号