顶部菜单分析

哔哩哔哩顶部导航菜单栏


通过观察可以发现,整个页面分为顶部导航和页面主体两个部分。而顶部导航在默认状态下为非固定状态,页面向下滚动时会遮盖住导航菜单。但是,当我们向下滚动一定距离后,导航栏会变为固定状态,即使页面滚动也始终保持在顶部。 直到将页面向上滚动到顶部后,导航栏又会恢复非固定状态。

所以,我们可以代码页面分为三个部分:

  • 非固定导航菜单栏
  • 固定导航菜单栏
  • 页面主体
    其中,默认显示非固定导航菜单栏,当页面向下滚动一定距离后,显示固定导航菜单栏。此时非固定导航菜单栏依旧存在,只是被固定导航菜单栏遮盖住了。

代码实现

页面模板

首先,先确定页面的三个部分,并通过css确定页面的大致布局:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<template>  
<div class="home">
<div class="navigation-bar">
非固定导航菜单栏
</div>
<div class="navigation-bar-fixed">
固定导航菜单栏
</div>
<div class="main-body">
页面主体
</div>
</div>
</template>
<style scoped>
.home {
min-width: 100vw;

.navigation-bar {
background: #dedede;
}

.navigation-bar-fixed {
background: #efefef;
}

.main-body {
background: #bcbcbc;
min-height: 120vh;
}
}
</style>

页面大致布局

核心设置

我们要控制固定导航栏在何时显示,因此可以使用v-if属性,并声明一个全局ref()作用于v-if。当showFixedtrue时,显示固定导航栏,默认隐藏。

1
2
3
4
5
6
7
8
9
10
11
<template>
...
<div class="navigation-bar-fixed" v-if="showFixed">
固定导航菜单栏
</div>
...
</template>

<script setup>
const showFixed = ref(false);
</script>

由于需要在向下滚动后将顶部导航栏改为固定格式,所以我们需要一个函数,获取向下滚动的像素并对showFixed的值做出处理。

1
2
3
4
5
6
7
8
9
10
11
const scrollBarHandle = () => {  
// 滚动条距离顶部的距离
let scrollDistance = window.scrollY;
// showFixed.value = scrollDistance >= 120;
// 如果滚动条离顶部超过120px,显示固定导航菜单栏,否则隐藏
if (scrollDistance >= 120) {
showFixed.value = true;
} else {
showFixed.value = false;
}
}

根据Vue3生命周期,我们可以将其放在onMounted中。

1
2
3
onMounted(() => {  
window.addEventListener('scroll', scrollBarHandle);
})

定位设置

最后,我们将固定导航栏的position设置为fixed即可。

1
2
3
4
5
6
7
.navigation-bar-fixed {  
background: #efefef;
position: fixed;
top: 0;
left: 0;
width: 100%;
}

然后,我们就得到了我们想要的效果。
成品展示


完整源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<template>  
<div class="home">
<div class="navigation-bar">
非固定导航菜单栏
</div>
<div class="navigation-bar-fixed" v-if="showFixed">
固定导航菜单栏
</div>
<div class="main-body">
页面主体
</div>
</div>
</template>

<script setup>
import {ref, onMounted} from "vue";

onMounted(() => {
// 监听滚动条距离顶部的距离
window.addEventListener('scroll', scrollBarHandle);
})

const showFixed = ref(false);

const scrollBarHandle = () => {
// 滚动条距离顶部的距离
let scrollDistance = window.scrollY;
// showFixed.value = scrollDistance >= 120;
// 如果滚动条离顶部超过120px,显示固定导航菜单栏,否则隐藏
if (scrollDistance >= 120) {
showFixed.value = true;
} else {
showFixed.value = false;
}
}
</script>

<style>
/* 修改body便于展示 */body {
background-color: #ffffff;
color: #1e1e1e;
font-size: 20px;
}

.home {
min-width: 100vw;

.navigation-bar {
background: #dedede;
}

.navigation-bar-fixed {
background: #efefef;
position: fixed;
top: 0;
left: 0;
width: 100%;
}

.main-body {
background: #bcbcbc;
min-height: 120vh;
}
}
</style>