最近給營銷市場部做了個H5頁面,頁面大概要求就是一個單獨的H5頁面,頂部導航欄固定含有三個導航按鈕必須和正文對應內容聯(lián)動。
首先想到需要用到錨點,但是單純的錨點功能會顯得滾動條很突兀一下子就跳到內容區(qū)了,效果很不理想,然后單純的一個H5頁面去引進jQuery庫肯定也是不合理的,所以必須自己去監(jiān)聽滾動條實現(xiàn)功能。

導航欄
<div class="header-main" :style="getColor()">
<div class="h5-header">
<div class="header-left"><i class="okicon icon-0121"></i></div>
<div class="header-right">
<span :class="{active: active == 0}">OKKONG OS</span>
<span :class="{active: active == 1}">系統(tǒng)亮點</span>
<span :class="{active: active == 2}">聯(lián)系客服</span>
</div>
</div>
</div>
固定導航欄css
其中有個小細節(jié)就是因為大div里設置了背景圖,導航欄的背景色要求是設置成0.15,這個時候我們背景色應該使用rgba,第四個參數(shù)寫上透明度0.15(小本本記好),這個就可以解決以后背景圖和背景色需要同時存在的情況了
.header-main{
min-width: 1200px;
background:rgba(255, 255, 255, 0.15);
position: fixed;
top:0;
left: 0;
right: 0;
}
設置選中導航按鈕的樣式
.active{
color: #FFA624;
border-bottom: 4px solid #FFA624;
font-weight: 800;
}
初始data里active值為0,默認選中第一個導航按鈕
data(){
return {
active: 0, // 當前激活的導航索引
scrollTop:'',//滾動距離
}
}
接下來我們就需要監(jiān)聽滾動事件handleScroll()
handleScroll () {
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop//獲取滾動距離
this.scrollTop = scrollTop//data里return了一個全局的scrollTop
console.log(scrollTop)
//這邊距離我是通過打印scrollTop大致自己粗略的計算了下,用來判斷滾輪滾動相應的距離改變導航欄對應菜單樣式
if (scrollTop > 1115) {
this.active = 1
}
if(scrollTop > 1850){
this.active = 2
}
if(scrollTop < 1000){
this.active = 0
}
}
頂部導航欄還有個樣式就是需要滾動下去時改變導航欄背景色,這個時候我們就需要給導航欄添加動態(tài)的style樣式
<div class="header-main" :style="getColor()">
樣式方法
getColor(){
//當滾動距離超過導航欄高度時改變背景色
if(this.scrollTop > 45){
return {
background:"#487DFE"
}
}else{
return false
}
}
最重要的一個環(huán)節(jié)就是給導航菜單欄添加點擊滾動事件scrollTo()
給三個導航按鈕增加點擊事件
<div class="header-right">
<span :class="{active: active == 0}" @click="scrollTo(1)">OKKONG OS</span>
<span :class="{active: active == 1}" @click="scrollTo(2)">系統(tǒng)亮點</span>
<span :class="{active: active == 2}" @click="scrollTo(3)">聯(lián)系客服</span>
</div>
定義scrollTo()方法
具體需要注意的地方和相應的解釋在代碼中已經給出
//跳轉到指定元素
scrollTo(val){
// 定義一次跳 50 個像素,數(shù)字越大跳得越快,但是會有掉幀得感覺
const STEP = 50
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop//獲取滾動距離
var targetOffsetTop = ''
if(val == 1){
targetOffsetTop = document.querySelector('.h5-os').offsetTop - 60//獲取指定元素視口距離
}
if(val == 2){
targetOffsetTop = document.querySelector('.h5-oslight').offsetTop - 60//獲取指定元素視口距離
}
if(val == 3){
targetOffsetTop = document.querySelector('.contactService').offsetTop - 60//獲取指定元素視口距離
}
if (scrollTop < targetOffsetTop) {
// 往下滑
smoothDown()
console.log(targetOffsetTop,'視口距離')
}else{
console.log(targetOffsetTop,'targetOffsetTop')
smoothUp()
}
// 定義下滑函數(shù)
function smoothDown() {
console.log(scrollTop,'scrollTop')
// 如果當前 scrollTop 小于 targetOffsetTop 說明視口還沒滑到指定位置
if (scrollTop < targetOffsetTop) {
// 如果和目標相差距離大于等于 STEP 就跳加上 STEP
// 否則直接跳到目標點,目標是為了防止跳過了。
if (targetOffsetTop - scrollTop >= STEP) {
scrollTop += STEP
} else {
scrollTop = targetOffsetTop
}
document.body.scrollTop = scrollTop
document.documentElement.scrollTop = scrollTop
// 屏幕在繪制下一幀時會回調傳給 requestAnimationFrame 的函數(shù)
// 關于 requestAnimationFrame 可以自己查一下,在這種場景下,相比 setInterval 性價比更高
requestAnimationFrame(smoothDown)
}
}
// 定義上滑函數(shù)
function smoothUp() {
// 如果當前 scrollTop 大于 targetOffsetTop 說明視口已經滑過指定位置需要上滑
if (scrollTop > targetOffsetTop) {
// 如果和目標相差距離大于等于 STEP 就跳減去 STEP
// 否則直接跳到目標點,目標是為了防止跳過了。
if (scrollTop - targetOffsetTop >= STEP) {
scrollTop -= STEP
} else {
scrollTop = targetOffsetTop
}
document.body.scrollTop = scrollTop
document.documentElement.scrollTop = scrollTop
// 屏幕在繪制下一幀時會回調傳給 requestAnimationFrame 的函數(shù)
// 關于 requestAnimationFrame 可以自己查一下,在這種場景下,相比 setInterval 性價比更高
requestAnimationFrame(smoothUp)
}
}
},
最后在mounted()中監(jiān)聽滾動事件,代碼如下
mounted() {
// 監(jiān)聽滾動事件
// document.getElementById("blockmain").addEventListener("scroll", this.handleScroll)
// window.addEventListener('scroll', this.handleScroll)
this.$nextTick(function () {
window.addEventListener('scroll', this.handleScroll)
})
},
需要注意的是在組件銷毀時我們需要移除滾動監(jiān)聽器,不然監(jiān)聽器會報錯
destroy() {
// 必須移除監(jiān)聽器,不然當該vue組件被銷毀了,監(jiān)聽器還在就會出錯
window.removeEventListener('scroll', this.handleScroll)
}
以上便是此次滾動事件平滑滾動和錨點雙向功能的實現(xiàn)邏輯