最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Vue3實(shí)現(xiàn)點(diǎn)擊Tab平滑滾動(dòng)并吸頂效果的完整代碼

 更新時(shí)間:2026年02月07日 09:34:09   作者:Mr Xu_  
在現(xiàn)代 Web 應(yīng)用開(kāi)發(fā)中,良好的用戶體驗(yàn)至關(guān)重要,本文將深入剖析一個(gè)常見(jiàn)的交互需求:點(diǎn)擊頁(yè)面 Tab 欄時(shí),頁(yè)面平滑滾動(dòng)至該 Tab 區(qū)域,并使其吸附在頂部導(dǎo)航欄下方的效果,需要的朋友可以參考下

前言

在現(xiàn)代 Web 應(yīng)用開(kāi)發(fā)中,良好的用戶體驗(yàn)至關(guān)重要。本文將深入剖析一個(gè)常見(jiàn)的交互需求:點(diǎn)擊頁(yè)面 Tab 欄時(shí),頁(yè)面平滑滾動(dòng)至該 Tab 區(qū)域,并使其吸附在頂部導(dǎo)航欄下方。我們將結(jié)合真實(shí)項(xiàng)目代碼,從實(shí)現(xiàn)原理、關(guān)鍵邏輯到最佳實(shí)踐進(jìn)行詳細(xì)講解。

一、需求背景

在頁(yè)面中,存在多個(gè) Tab(如“公司簡(jiǎn)介”、“資質(zhì)榮譽(yù)”等)。用戶點(diǎn)擊任意 Tab 時(shí),期望:

  1. 頁(yè)面平滑滾動(dòng),使 Tab 欄剛好位于頂部導(dǎo)航(Header)下方;
  2. 滾動(dòng)完成后,Tab 欄固定吸附在 Header 下方,隨頁(yè)面滾動(dòng)保持位置不變;
  3. 同時(shí)更新路由和子組件內(nèi)容。

注意:本項(xiàng)目使用 Vue3 + <script setup> + Less,滾動(dòng)容器為自定義 .layout(非 window),且僅針對(duì) PC 端。

二、核心實(shí)現(xiàn)思路

要實(shí)現(xiàn)上述效果,需解決兩個(gè)關(guān)鍵問(wèn)題:

1.如何讓元素“吸頂”?

使用 CSS position: sticky

  • 設(shè)置 top: 95px(與 Header 高度一致)
  • 元素在滾動(dòng)到指定位置時(shí)自動(dòng)固定

2.如何平滑滾動(dòng)到目標(biāo)位置?

計(jì)算目標(biāo)元素相對(duì)于滾動(dòng)容器的偏移量
調(diào)用 scrollTo({ top: target, behavior: 'smooth' })

三、代碼分析(以index.vue為例)

1. 模板結(jié)構(gòu)(關(guān)鍵部分)

<template>
  <div class="container">
    <!-- 背景圖 -->
    <div class="bgpic">...</div>
    
    <!-- Tab 欄(添加 ref 用于獲取 DOM) -->
    <div class="tab" :class="{'h5-tab': isMobile}" ref="tabRef">
      <div class="tab-box">
        <div class="tab-content">
          <span 
            v-for="item in sortedMenuList" 
            :key="item.id"
            @click="handleChose(item)"
            :class="{ 'current-tab': currentTab == item.menuName }"
          >
            {{ item.menuName }}
          </span>
        </div>
      </div>
    </div>

    <!-- 內(nèi)容區(qū)(各 Tab 對(duì)應(yīng)組件) -->
    <div class="content">
      <div v-show="currentTab == '流域項(xiàng)目'">...</div>
      <div v-show="currentTab == '省級(jí)項(xiàng)目'">...</div>
      ...
    </div>
  </div>
</template>

關(guān)鍵點(diǎn):給 .tab 添加 ref="tabRef",便于 JS 獲取其 DOM 位置。

2. CSS 吸頂樣式(Less)

.tab {
  height: 96px;
  background-color: #eee;
  display: flex;
  justify-content: center;
  align-items: center;
  
  /* ?? 核心:sticky 定位實(shí)現(xiàn)吸頂 */
  position: sticky;
  top: 95px; /* 與 App.vue 中 .content 的 padding-top 一致 */
  z-index: 10;
}

為什么是 95px?
查看 App.vue 可知:

.content { padding-top: v-bind('isWelcome ? 0 : "95px"'); }

非首頁(yè)時(shí),.content 上邊距為 95px,即 Header 高度。因此 Tab 吸頂位置為 top: 95px。

3. JavaScript 邏輯:handleChose方法

const handleChose = (val, skipAnimation = false) => {
  // 1. 更新當(dāng)前 Tab 和菜單 ID
  currentTab.value = val.menuName;
  menuId.value = val.id;

  // 2. 重置子組件狀態(tài)(略)

  // 3. 【關(guān)鍵】移動(dòng)端或跳過(guò)動(dòng)畫時(shí)直接返回
  if (isMobile.value || skipAnimation) return;

  // 4. 平滑滾動(dòng)到 Tab 位置
  nextTick(() => {
    const bgpic = document.querySelector('.bgpic');
    const bgpicHeight = bgpic ? bgpic.offsetHeight : 0;
    const layout = document.querySelector('.layout');
    
    if (layout) {
      setTimeout(() => {
        // 目標(biāo)滾動(dòng)位置 = 背景圖高度(即 Tab 的 offsetTop)
        layout.scrollTo({
          top: bgpicHeight,
          behavior: 'smooth'
        });
      }, 0);
    }
  });
};

代碼解析:

bgpicHeight 即 Tab 的 offsetTop
因?yàn)?.tab 緊跟在 .bgpic 后,且 .bgpic 高度固定為 550px,所以 bgpic.offsetHeight 就是 Tab 距離容器頂部的距離。

為什么用 setTimeout
確保 DOM 更新完成后再執(zhí)行滾動(dòng)(雖然 nextTick 已保證,但雙重保險(xiǎn))。

為什么不直接計(jì)算 tabRef.value.offsetTop
在復(fù)雜布局中,offsetTop 可能受父元素定位影響。而本項(xiàng)目結(jié)構(gòu)簡(jiǎn)單(.bgpic.tab),直接用背景圖高度更可靠。

注意:此寫法依賴固定布局。若 Tab 位置動(dòng)態(tài)變化,應(yīng)改用通用方法計(jì)算 offsetTop(見(jiàn)下文優(yōu)化建議)。

四、優(yōu)化建議(通用方案)

如果 Tab 位置不固定,可采用以下通用方法計(jì)算偏移量:

// 通用獲取元素相對(duì)于滾動(dòng)容器的 offsetTop
function getOffsetTop(element, container) {
  let offsetTop = 0;
  let el = element;
  while (el && el !== container && el !== document.body) {
    offsetTop += el.offsetTop;
    el = el.offsetParent;
  }
  return offsetTop;
}

// 在 handleChose 中使用
nextTick(() => {
  const layout = document.querySelector('.layout');
  const tabEl = tabRef.value;
  if (layout && tabEl) {
    const offsetTop = getOffsetTop(tabEl, layout);
    const headerHeight = 95; // 或動(dòng)態(tài)獲取
    layout.scrollTo({
      top: offsetTop - headerHeight,
      behavior: 'smooth'
    });
  }
});

五、總結(jié)

技術(shù)點(diǎn)實(shí)現(xiàn)方式說(shuō)明
吸頂效果position: sticky; top: 95px利用 CSS 原生能力,性能好
平滑滾動(dòng)element.scrollTo({ behavior: 'smooth' })原生 API,無(wú)需第三方庫(kù)
位置計(jì)算利用背景圖高度 / 通用 offsetTop 計(jì)算根據(jù)項(xiàng)目結(jié)構(gòu)選擇
響應(yīng)式處理移動(dòng)端跳過(guò)滾動(dòng)邏輯提升移動(dòng)端體驗(yàn)

通過(guò)以上方案,我們實(shí)現(xiàn)了點(diǎn)擊 Tab → 平滑滾動(dòng) → 吸頂固定的完整交互,既滿足了產(chǎn)品需求,又保證了代碼的可維護(hù)性。

最佳實(shí)踐:優(yōu)先使用 CSS sticky 實(shí)現(xiàn)吸頂,JS 僅負(fù)責(zé)觸發(fā)滾動(dòng);避免用 JS 動(dòng)態(tài)修改 position,減少重繪開(kāi)銷。

以上就是基于Vue3實(shí)現(xiàn)點(diǎn)擊Tab平滑滾動(dòng)并吸頂效果的完整代碼的詳細(xì)內(nèi)容,更多關(guān)于Vue3點(diǎn)擊Tab平滑滾動(dòng)并吸頂?shù)馁Y料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • elementUI中input回車觸發(fā)頁(yè)面刷新問(wèn)題與解決方法

    elementUI中input回車觸發(fā)頁(yè)面刷新問(wèn)題與解決方法

    這篇文章主要給大家介紹了關(guān)于elementUI中input回車觸發(fā)頁(yè)面刷新問(wèn)題與解決方法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用elementUI具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2023-07-07
  • vue-cli創(chuàng)建的項(xiàng)目中的gitHooks原理解析

    vue-cli創(chuàng)建的項(xiàng)目中的gitHooks原理解析

    這篇文章主要介紹了vue-cli創(chuàng)建的項(xiàng)目中的gitHooks原理解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • Vue中指令v-model的原理及使用方法

    Vue中指令v-model的原理及使用方法

    v-model是Vue中的一個(gè)重要語(yǔ)法糖,主要用于實(shí)現(xiàn)數(shù)據(jù)的雙向綁定,它通過(guò)結(jié)合value屬性和input事件,簡(jiǎn)化了代碼并提高了開(kāi)發(fā)效率,文中通過(guò)代碼介紹的非常詳解,需要的朋友可以參考下
    2024-09-09
  • vue-cli 首屏加載優(yōu)化問(wèn)題

    vue-cli 首屏加載優(yōu)化問(wèn)題

    這篇文章主要介紹了vue-cli 首屏加載優(yōu)化問(wèn)題,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-11-11
  • vue加載自定義的js文件方法

    vue加載自定義的js文件方法

    下面小編就為大家分享一篇vue加載自定義的js文件方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03
  • web前端vue之vuex單獨(dú)一文件使用方式實(shí)例詳解

    web前端vue之vuex單獨(dú)一文件使用方式實(shí)例詳解

    Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開(kāi)發(fā)的狀態(tài)管理模式。這篇文章主要介紹了web前端vue:vuex單獨(dú)一文件使用方式,需要的朋友可以參考下
    2018-01-01
  • Vue項(xiàng)目中Websocket的使用實(shí)例

    Vue項(xiàng)目中Websocket的使用實(shí)例

    WebSocket就誕生了,它最大特點(diǎn)就是服務(wù)器可以主動(dòng)向客戶端推送信息,客戶端也可以主動(dòng)向服務(wù)器發(fā)送信息,是真正的雙向平等對(duì)話,下面這篇文章主要給大家介紹了關(guān)于Vue項(xiàng)目中Websocket使用的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • 解決Element中el-date-picker組件不回填的情況

    解決Element中el-date-picker組件不回填的情況

    這篇文章主要介紹了解決Element中el-date-picker組件不回填的情況,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-11-11
  • vue中實(shí)時(shí)監(jiān)聽(tīng)div元素盒子的寬高方法

    vue中實(shí)時(shí)監(jiān)聽(tīng)div元素盒子的寬高方法

    這篇文章主要給大家介紹了關(guān)于vue中如何實(shí)時(shí)監(jiān)聽(tīng)div元素盒子的寬高的相關(guān)資料,在Vue中你可以使用Vue的計(jì)算屬性和偵聽(tīng)器來(lái)動(dòng)態(tài)監(jiān)測(cè)元素的高度,文中給出了簡(jiǎn)單代碼示例,需要的朋友可以參考下
    2023-09-09
  • 詳解最新vue-cli 2.9.1的webpack存在問(wèn)題

    詳解最新vue-cli 2.9.1的webpack存在問(wèn)題

    這篇文章主要介紹了最新vue-cli 2.9.1的webpack存在問(wèn)題,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12

最新評(píng)論

鸡泽县| 玛沁县| 昌乐县| 南漳县| 运城市| 灌阳县| 沂南县| 牙克石市| 临邑县| 克拉玛依市| 棋牌| 大方县| 通许县| 仁怀市| 蒙城县| 古丈县| 黄龙县| 嫩江县| 峡江县| 双牌县| 开阳县| 沿河| 静乐县| 武义县| 江门市| 西华县| 灵川县| 安仁县| 宝兴县| 梁平县| 新田县| 丹江口市| 格尔木市| 台东县| 木兰县| 和顺县| 景谷| 德钦县| 云安县| 天门市| 万安县|