欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue3如何實現(xiàn)錨點定位點擊滾動高亮

 更新時間:2024年04月28日 08:54:04   作者:易de  
這篇文章主要介紹了vue3如何實現(xiàn)錨點定位點擊滾動高亮問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

功能描述

點擊導航跳到對應模塊的起始位置,并且高亮點擊的導航;

滾動到相應的模塊時,對應的導航也自動高亮;

效果展示

在這里插入圖片描述

注意事項

  • 一定要明確哪個是要滾動的盒子;
  • 滾動的高度要減去導航欄的高度;
  • 當前在導航1,點擊導航4時,會出現(xiàn)導航2、導航3和導航4依次高亮的現(xiàn)象,定義變量判斷當前為點擊時不監(jiān)聽滾動事件即可;
    isScroll.value = false

核心代碼

onMounted(() => {
  nextTick(() => {
  	// 監(jiān)聽滾動的盒子的滾動事件
    document.getElementById('scrollBox').addEventListener("scroll", onScroll);
  })
})

onBeforeUnmount(() => {
  document.getElementById('scrollBox').removeEventListener('scroll', onScroll)
})


const scrollToAnchor = (id, index) => {
 activeIndex.value = index
  var anchor = document.getElementById(id);
  var scrollBox = document.getElementById('scrollBox')
  nextTick(() => {
    scrollBox.scrollTo({
      top: anchor.offsetTop - 30,
      behavior: 'smooth'
    });
 })
  isScroll.value = false
   // 點擊時暫停頁面的滾動監(jiān)聽事件,防止點擊時導航高亮出現(xiàn)走馬燈效果;
  // 此處的定時器存在缺陷,點擊完2秒之內滾動還是會偶現(xiàn)走馬燈現(xiàn)象;
  let timeId = '';
  clearTimeout(timeId);
  timeId = setTimeout(() => {
    isScroll.value = true;
  }, 2000);
};


// 滾動監(jiān)聽器
const onScroll = ()=> {
  if(!isScroll.value) return
  // 獲取所有錨點元素
  const navContents = document.querySelectorAll('.container .section')
  // 所有錨點元素的 offsetTop
  const offsetTopArr = []
  navContents.forEach(item => {
    offsetTopArr.push(item.offsetTop-30)
  })
  // 獲取當前文檔流的 scrollTop
  const scrollTop = document.getElementById('scrollBox').scrollTop
  // 定義當前點亮的導航下標
  let navIndex = 1
  for (let n = 1; n <= offsetTopArr.length; n++) {
    // 如果 scrollTop 大于等于第 n 個元素的 offsetTop 則說明 n-1 的內容已經(jīng)完全不可見
    // 那么此時導航索引就應該是 n 了
    if (scrollTop >= offsetTopArr[n-1]) {
      navIndex = n
    }
  }
  // 把下標賦值給 vue 的 data
  activeIndex.value = navIndex
}

完整代碼

<template>
  <div class="box" id="scrollBox" v-loading="loading">
    <div class="fixed-box">
      <div v-for="(i) in defaultTabs" :class="{active_anchor: activeIndex === i}">
          <a @click="scrollToAnchor(`section${i}`, i)">
            <span v-if="i == 1">導航1</span>
            <span v-if="i == 2">導航2</span>
            <span v-if="i == 3">導航3</span>
            <span v-if="i == 4">導航4</span>
            <span v-if="i == 5">導航5</span>
          </a>
        </div>
    </div>
    <div class="container" id="printcontent">
      <div class="section" id="section1">
        <h3>日歷</h3>
        <el-calendar v-model="value" />
      </div>
      <div class="section" id="section2">
        <h3>帶邊框列表</h3>
        <el-descriptions class="margin-top" title="" :column="4" border>
          <template v-for="i in 4">
            <el-descriptions-item label="Username">kooriookami</el-descriptions-item>
            <el-descriptions-item label="Telephone">18100000000</el-descriptions-item>
            <el-descriptions-item label="Place" :span="2">Suzhou</el-descriptions-item>
            <el-descriptions-item label="Remarks">123123</el-descriptions-item>
            <el-descriptions-item label="Username">一一一</el-descriptions-item>
            <el-descriptions-item label="Remarks">123123</el-descriptions-item>
            <el-descriptions-item label="Remarks">-</el-descriptions-item>
            <el-descriptions-item label="Remarks">-</el-descriptions-item>
            <el-descriptions-item label="Remarks">-</el-descriptions-item>
          </template>
        </el-descriptions>
      </div>
      <div class="section" id="section3">
        <h3>普通表格</h3>
        <el-table :data="tableData" style="width: 100%">
          <el-table-column prop="date" label="Date" width="180" />
          <el-table-column prop="name" label="Name" width="180" />
          <el-table-column prop="address" label="Address" />
        </el-table>
      </div>
      <div class="section" id="section4">
        <h3>普通卡片</h3>
        <el-card class="box-card">
          <template #header>
            <div class="card-header">
              <span>Card name</span>
              <el-button class="button" text>Operation button</el-button>
            </div>
          </template>
          <div v-for="o in 10" :key="o" class="text item">{{ 'List item ' + o }}</div>
          <template #footer>Footer content</template>
        </el-card>
      </div>
    </div>
  </div>
</template>
<script setup>
import { onMounted, ref, nextTick, onBeforeUnmount } from 'vue'
const loading = ref(false)
const value = ref(new Date())
const defaultTabs = ref([1, 2, 3, 4, 5])
const activeIndex = ref(1)
const isScroll = ref(true) // 點擊導航欄時,暫時停止監(jiān)聽頁面滾動
const tableData = [
  {
    date: '2016-05-03',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-02',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-04',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-01',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-04',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-01',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-04',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-01',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-04',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-01',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-04',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
  {
    date: '2016-05-01',
    name: 'Tom',
    address: 'No. 189, Grove St, Los Angeles',
  },
]

onMounted(() => {
  nextTick(() => {
    document.getElementById('scrollBox').addEventListener("scroll", onScroll);
  })
})

onBeforeUnmount(() => {
  document.getElementById('scrollBox').removeEventListener('scroll', onScroll)
})

const scrollToAnchor = (id, index) => {
 activeIndex.value = index
  var anchor = document.getElementById(id);
  var scrollBox = document.getElementById('scrollBox')
  nextTick(() => {
    scrollBox.scrollTo({
      top: anchor.offsetTop - 30,
      behavior: 'smooth'
    });
 })
  // 點擊時暫停頁面的滾動監(jiān)聽事件,防止點擊時導航高亮出現(xiàn)走馬燈效果;
  // 此處的定時器存在缺陷,點擊完2秒之內滾動還是會偶現(xiàn)走馬燈現(xiàn)象;
  isScroll.value = false
  let timeId = '';
  clearTimeout(timeId);
  timeId = setTimeout(() => {
    isScroll.value = true;
  }, 2000);
};

// 滾動監(jiān)聽器
const onScroll = ()=> {
  if(!isScroll.value) return
  // 獲取所有錨點元素
  const navContents = document.querySelectorAll('.container .section')
  // 所有錨點元素的 offsetTop
  const offsetTopArr = []
  navContents.forEach(item => {
    offsetTopArr.push(item.offsetTop-30)
  })
  // 獲取當前文檔流的 scrollTop
  const scrollTop = document.getElementById('scrollBox').scrollTop
  // 定義當前點亮的導航下標
  let navIndex = 1
  for (let n = 1; n <= offsetTopArr.length; n++) {
    // 如果 scrollTop 大于等于第 n 個元素的 offsetTop 則說明 n-1 的內容已經(jīng)完全不可見
    // 那么此時導航索引就應該是 n 了
    if (scrollTop >= offsetTopArr[n-1]) {
      navIndex = n
    }
  }
  // 把下標賦值給 vue 的 data
  activeIndex.value = navIndex
}

</script>
<style scoped lang="scss">
.box{
  // width: 98%;
  margin: auto;
  height: 100%;
  overflow: auto;
}
.fixed-box{
  width: calc(100% - 200px);
  background: white;
  position: fixed;
  top: 84px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  z-index: 99;
  padding: 5px 30px;
  box-sizing: border-box;
  box-shadow: 1px 1px 1px #ccc;
  span {
    padding: 0 10px;
    list-style: none;
  }
}
.container {
  padding-top: 15px;
  position: relative;
}
.section {
  margin: 20px 0;
}
:deep(.el-tabs ){
  --el-tabs-header-height: 50px;
}
.active_anchor {
  color: #409eff;
}
</style>

總結

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • vue實現(xiàn)原理this.$message實例詳解

    vue實現(xiàn)原理this.$message實例詳解

    這篇文章主要介紹了vue實現(xiàn)原理this.$message實例詳解,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2024-03-03
  • 詳解Vite的新體驗

    詳解Vite的新體驗

    這篇文章主要介紹了詳解Vite的新體驗,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-02-02
  • vue input實現(xiàn)點擊按鈕文字增刪功能示例

    vue input實現(xiàn)點擊按鈕文字增刪功能示例

    這篇文章主要介紹了vue input實現(xiàn)點擊按鈕文字增刪功能,涉及基于vue.js的事件響應及頁面元素屬性動態(tài)操作相關實現(xiàn)技巧,需要的朋友可以參考下
    2019-01-01
  • vue.js實現(xiàn)選項卡切換

    vue.js實現(xiàn)選項卡切換

    這篇文章主要為大家詳細介紹了vue.js實現(xiàn)選項卡切換功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • vue封裝echarts組件,數(shù)據(jù)動態(tài)渲染方式

    vue封裝echarts組件,數(shù)據(jù)動態(tài)渲染方式

    這篇文章主要介紹了vue封裝echarts組件,數(shù)據(jù)動態(tài)渲染方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • go-gin-vue3-elementPlus帶參手動上傳文件的案例代碼

    go-gin-vue3-elementPlus帶參手動上傳文件的案例代碼

    這篇文章主要介紹了go-gin-vue3-elementPlus帶參手動上傳文件的案例代碼,本文結合實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2023-11-11
  • vscode使用Eslint+Prettier格式化代碼的詳細操作

    vscode使用Eslint+Prettier格式化代碼的詳細操作

    這篇文章主要介紹了vscode使用Eslint+Prettier格式化代碼,本文通過圖文示例代碼相結合給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-08-08
  • vue中router-view使用教程詳解

    vue中router-view使用教程詳解

    router-view組件作為vue最核心的路由管理組件,在項目中作為路由管理經(jīng)常被使用到,本文主要為大家詳細介紹了router-view具體使用,希望對大家有所幫助
    2023-12-12
  • vue3+vite中使用vuex的具體步驟

    vue3+vite中使用vuex的具體步驟

    在vue3+vite創(chuàng)建的項目中使用vuex,要注意的是vite有部分寫法和之前的webpack是不同的,這篇文章主要介紹了vue3+vite中使用vuex的具體步驟,需要的朋友可以參考下
    2022-11-11
  • vue使用websocket連接優(yōu)化性能方式

    vue使用websocket連接優(yōu)化性能方式

    這篇文章主要介紹了vue使用websocket連接優(yōu)化性能方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-10-10

最新評論