超详细Vue实现导航栏绑定内容锚点+滚动动画+vue-router(hash模式可用)

摘要:
--内容区域--˃内容-Content-1Content-2Content-3Content-4//div˃˂!

超详细Vue实现导航栏绑定内容锚点+滚动动画+vue-router(hash模式可用)

转载自:https://www.jianshu.com/p/2ad8c8b5bf75

亲测有效~

<template>
  <div>
    <!-- 内容区域 -->
    <div class="content">
      <div>
        content-0
      </div>
      <div>
        content-1
      </div>
      <div>
        content-2
      </div>
      <div>
        content-3
      </div>
      <div>
        content-4
      </div>
    </div>
    <!-- 导航区域 -->
    <ul class="navs">
      <li :  @click="scrollTo(0)">
        content-0
      </li>
      <li :  @click="scrollTo(1)">
        content-1
      </li>
      <li :  @click="scrollTo(2)">
        content-2
      </li>
      <li :  @click="scrollTo(3)">
        content-3
      </li>
      <li :  @click="scrollTo(4)">
        content-4
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  props: {},
  data() {
    return {
      active: 0 // 当前激活的导航索引
    }
  },
  mounted() {
    // 监听滚动事件
    window.addEventListener('scroll', this.onScroll, false)
  },
  destroy() {
    // 必须移除监听器,不然当该vue组件被销毁了,监听器还在就会出错
    window.removeEventListener('scroll', this.onScroll)
  },
  methods: {
    // 滚动监听器
    onScroll() {
      // 获取所有锚点元素
      const navContents = document.querySelectorAll('.content div')
      // 所有锚点元素的 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
        }
      }
      this.active = navIndex
    },
    // 跳转到指定索引的元素
    scrollTo(index) {
      // 获取目标的 offsetTop
      // css选择器是从 1 开始计数,我们是从 0 开始,所以要 +1
      const targetOffsetTop = document.querySelector(`.content div:nth-child(${index + 1})`).offsetTop
      // 获取当前 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)
        }
      }
    }
  }
}
</script>

<style scoped>
  /* 内容区的样式 */
  .content {
    background-color: white;
     500px;
  }
  .content div {
     100%;
    height: 600px;
    font-size: 36px;
    padding: 20px;
    background-color: #7ec384;
  }
  .content div:nth-child(2n) {
    background-color: #847ec3;
  }
  /* 导航栏的样式 */
  .navs {
    position: fixed;
    top: 80px;
    left: 700px;
    background-color: #efefef;
  }
  .navs li {
    padding: 0 20px;
    line-height: 1.6;
    font-size: 24px;
  }
  /* 当导航被点亮后改变颜色 */
  .navs .active{
    color: #847ec3;
    background-color: #e2e2e2;
  }
</style>

免责声明:文章转载自《超详细Vue实现导航栏绑定内容锚点+滚动动画+vue-router(hash模式可用)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇9.Redis详解(九)------ 哨兵(Sentinel)模式详解Springboot 解析 json 并返回+ Jsoup介绍及解析常用方法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

初学vue出现空格警告的原因及其解决办法

初学vue自己新建一个vue项目来做学习demo。不过在编写代码时一直出现空格不规范的警告。严重影响初学者的热情。错误如下图所示。(这样的错误很多,但大概翻译成中文的意思都是说空格使用不规范。) 这是因为你使用 ESLint,用来规范代码风格的。你的 Webpack 配置中大概是使用了 eslint-loader。在多人协作或大项目中推荐使用,不想要就在 ...

Vue + Element UI 实现权限管理系统 前端篇(七):功能组件封装

因为我暂时不需要第五章和第六章教程的内容所以直接进入第七章。感兴趣的可以访问原作者网站 Vue + Element UI 实现权限管理系统 前端篇(六):更换皮肤主题  Vue + Element UI 实现权限管理系统 前端篇(五):国际化实现  注:本次封装的css样式应该有点问题,但考虑时间问题没有认真修改,后续有时间重构时候补上。 组件...

VUE 使用中踩过的坑

vue如今可谓是一匹黑马,github star数已居第一位!前端开发对于vue的使用已经越来越多,它的优点就不做介绍了,本篇是我对vue使用过程中以及对一些社区朋友提问我的问题中做的一些总结,帮助大家踩坑。如果喜欢的话可以点波赞,或者关注一下,希望本文可以帮到大家! 1.路由变化页面数据不刷新问题 出现这种情况是因为依赖路由的params参数获取写在cr...

vue3+ts +vant 从0搭建移动端架子

1. 前期准备 安装node,vue3,vscode 1.1 安装更新脚手架npm install -g @vue/clinpm update -g @vue/cli 1.2 vscode 插件Volar ,Vue 3 Snippets 开发vue3时需要关闭vetur插件 2. vue3官网 https://v3.cn.vuejs.org/ vant 官...

循序渐进VUE+Element 前端应用开发(19)--- 后端查询接口和Vue前端的整合

循序渐进VUE+Element 前端应用开发的系列文章中,前面介绍了系统各个功能的处理实现,本篇随笔从一个主线上介绍前后端开发的整合,让我们从ABP框架后端的查询接口的处理,前端API接口调用的封装,以及前端Element界面的整个调用过程进行一个完整的介绍。 我们前面介绍了Vue+Element前端的接口是调用后端的ABP框架发布的API接口服务,API...

HTML页面过渡效果大全

IE要求:  在IE5.5及以上版本的浏览器中.启用网页过渡效果  默认情况下都已经启用了,如果需要手动启用则只需在Internet选项中: Advanced(高级) - Browsing(浏览) - Enable page transitions(启用页面过渡)即可。应用过渡效果  当我们需要添加过渡效果时,只需在<head>中添加一个特殊的...