vue橫向導航條滾動到頂部固定同時瞄點對應內容(copy即用)


這里監聽window 的scroll實現一個頁面滾動,導航菜單定位,內容聯動的一個簡單組件,結合一些案例,按需進行了整合,在此記錄一下

效果圖如下


具體實現如下


一、先創建一個NavigateTool.vue導航組件

html


<template>
    <div class="searchBar navigate__bar">
        <ul :class="searchBarFixed == true ? 'isFixed' :''">
            <li :class="{active: navIndex===0}" @click="scrollTo(0)">區域</li>
            <li :class="{active: navIndex===1}" @click="scrollTo(1)">國界</li>
            <li :class="{active: navIndex===2}" @click="scrollTo(2)">宇宙</li>
            <li :class="{active: navIndex===3}" @click="scrollTo(3)">銀河</li>
        </ul>
    </div>
</template>

js

1、mounted()中 監聽頁面滾動

    mounted() {
            // 監聽滾動事件
            window.addEventListener('scroll', this.onScroll, false)
        },

2、 destroy() 中注銷監聽
        destroy() {
            // 必須移除監聽器,不然當該vue組件被銷毀了,監聽器還在就會出錯
            window.removeEventListener('scroll', this.onScroll)
        },
3、data掛載當前激活導航id

    data(){
          return{
              navIndex:0,
              searchBarFixed:false,
          }
        },
4、methods中添加 監聽頁面滾動事件方法
	/** * 頁面滾動事件監聽 */
  onScroll() {
        // 獲取所有錨點元素
           const navContents = document.querySelectorAll('.home__content_comp div')
           console.log(navContents.length)
           // 所有錨點元素的 offsetTop
           const offsetTopArr = []
           navContents.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個元素的 offsetTop 則說明 n-1 的內容已經完全不可見
               // 那么此時導航索引就應該是n了
               if (scrollTop >=offsetTopArr[n]) {
                   navIndex = n+1
               }
           }
           navIndex = navIndex >= navContents.length? navIndex-1:navIndex;
           console.log(navIndex)
           this.navIndex = navIndex

           // 組件吸附頂部
           var offsetTop = document.querySelector('.navigate__bar').offsetTop;
           if (scrollTop > offsetTop) {
               this.searchBarFixed = true;
           } else {
               this.searchBarFixed = false;
           }
    },
5、methods中添加導航菜單點擊事件(計算頁面滾動位置與組件距離頂部距離)
         
   /** * 跳轉到指定索引的元素 * @param index */
    scrollTo(index) {
        // 獲取目標的 offsetTop
        // css選擇器是從 1 開始計數,我們是從 0 開始,所以要 +1
        // const foundEl = document.querySelector(`.home__content_comp div:nth-child(${index + 1})`);
        // const elClientHeight = foundEl.clientHeight;

        const targetOffsetTop = document.querySelector(`.home__content_comp div:nth-child(${index+1})`).offsetTop-40
        // 獲取當前 offsetTop
        let scrollTop = document.documentElement.scrollTop || document.body.scrollTop
        // 定義一次跳 50 個像素,數字越大跳得越快,但是會有掉幀得感覺,步子邁大了會扯到蛋
        const STEP = 50
        // 判斷是往下滑還是往上滑
        if (scrollTop > targetOffsetTop) {
            // 往上滑
            smoothUp()
        } else {
            // 往下滑
            smoothDown()
        }
        // 定義往下滑函數
        function smoothDown() {
            // 如果當前 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 可以自己查一下,在這種場景下,相比 setInterval 性價比更高
                requestAnimationFrame(smoothDown)
            }
        }
        // 定義往上滑函數
        function smoothUp() {
            if (scrollTop > targetOffsetTop) {
                if (scrollTop - targetOffsetTop >= STEP) {
                    scrollTop -= STEP
                } else {
                    scrollTop = targetOffsetTop
                }
                document.body.scrollTop = scrollTop
                document.documentElement.scrollTop = scrollTop
                requestAnimationFrame(smoothUp)
            }
        }
    }

css


	<style scoped lang="scss">
	    .searchBar {
	        width: 100%;
	        .isFixed {
	            position: fixed;
	            width: 100%;
	            top: 0;
	            left: 0;
	            z-index: 999;
	        }
	        ul {
	            height: 40px;
	            line-height: 40px;
	            display: flex;
	            margin:0;
	            padding: 0;
	
	            li {
	                font-size: 0.8rem;
	                flex: 1;
	                display: flex;
	                justify-items: center;
	                justify-content: center;
	                align-items: center;
	                align-content: center;
	                position: relative;
	                background-color: #fff;
	                &.active {
	                    color: #847ec3;
	                    background-color: #e2e2e2;
	                    &:after {
	                        content: " ";
	                        position: absolute;
	                        height: 1px;
	                        width: 30px;
	                        bottom: 6px;
	                        left:calc(50% - 15px);
	                        border-top: 2px #847ec3 solid;
	                    }
	                }
	            }
	        }
	    }
	
	</style>
	

二、再建個HomeContent.vue

這個頁面就比較簡單了


	<template>
	    <div>
	        <naigate-tool></naigate-tool>
	        <!-- 內容區域 -->
	        <div class="home__content_comp">
	            <div>
	                This is first page.
	            </div>
	            <div>
	                This is second page.
	            </div>
	            <div>
	                This is third page.
	            </div>
	            <div>
	                This is fourth page.
	            </div>
	
	        </div>
	    </div>
	</template>
	
	<script type="text/ecmascript-6">
	    import  NaigateTool from './NavigateTool';
	
	    export default {
	        name:'HomeContent',
	        components:{
	            NaigateTool
	        }
	
	    }
	</script>
	
	<style scoped>
	    /* 內容區的樣式 */
	    .home__content_comp {
	        background-color: white;
	        width: 100%;
	    }
	    .home__content_comp div {
	        width: 100%;
	        height: 600px;
	        font-size: 26px;
	
	        background-color: #7ec384;
	    }
	    .home__content_comp div:nth-child(2n) {
	        background-color: #847ec3;
	    }
	
	</style>

參考案例:

超詳細Vue實現導航欄綁定內容錨點+滾動動畫

vue的滾動scroll事件 實現某元素吸頂或者固定位置顯示


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM