Vue锚点双向定位

 <div class="sidebar">
      <div :class="{ active: active == 0 }" @click="scrollTo(0)">基本信息</div>
      <div :class="{ active: active == 1 }" @click="scrollTo(1)">企业风采</div>
      <div :class="{ active: active == 2 }" @click="scrollTo(2)">资质荣誉</div>
      <div :class="{ active: active == 3 }" @click="scrollTo(3)">产品服务</div>
      <div :class="{ active: active == 4 }" @click="scrollTo(4)">技术成果</div>
      <div :class="{ active: active == 5 }" @click="scrollTo(5)">专家人才</div>
      <div :class="{ active: active == 6 }" @click="scrollTo(6)">合作机会</div>
      <div :class="{ active: active == 7 }" @click="scrollTo(7)">热招职位</div>
    </div>

data() {
      return {
       
        active: 0, // 当前激活的导航索引
      }
    },
 mounted() {
      // 监听滚动事件
      window.addEventListener('scroll', this.onScroll, false)
    },
    destroy() {
      // 必须移除监听器,不然当该vue组件被销毁了,监听器还在就会出错
      window.removeEventListener('scroll', this.onScroll)
    },

methods: {
      // 滚动监听器
      onScroll() {
        // let scrollTop = 0
        // 获取所有锚点元素
        const navContents = document.querySelectorAll('.element')
        // 所有锚点元素的 offsetTop
        const offsetTopArr = []
        navContents.forEach((item) => {
          offsetTopArr.push(item.offsetTop)
        })
        // 获取当前文档流的 scrollTop
        let scrollTop =
          document.documentElement.scrollTop || document.body.scrollTop || 0
        // 定义当前点亮的导航下标
        let navIndex = 0
        for (let n = 0; n < offsetTopArr.length; n++) {
          // 如果 scrollTop 大于等于第n个元素的 offsetTop 则说明 n-1 的内容已经完全不可见
          // 那么此时导航索引就应该是n了
          if (scrollTop >= offsetTopArr[n]) {
            navIndex = n
          }
          if (
            scrollTop + document.documentElement.clientHeight ===
            document.documentElement.scrollHeight
          ) {
            navIndex = offsetTopArr.length - 1
          }
        }
        this.active = navIndex
        // scrollTo(0)
      },
      // 跳转到指定索引的元素
      scrollTo(index) {
        // 获取目标的 offsetTop
        // css选择器是从 1 开始计数,我们是从 0 开始,所以要 +1
        const targetOffsetTop = document.querySelector(
          `.element:nth-child(${index+3})`//加三应该因为之前有三个元素,这里要有改动
        ).offsetTop
        // console.log(index,'index');
        // console.log(targetOffsetTop,'targetOffsetTop');
        // 获取当前 offsetTop
        let scrollTop =
          document.documentElement.scrollTop || document.body.scrollTop
        // 定义一次跳 50 个像素,数字越大跳得越快,但是会有掉帧得感觉,步子迈大了会扯到蛋
        const STEP = 100
        // 判断是往下滑还是往上滑
        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)
          }
        }
      },
    },

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值