vue3实现导航栏绑定内容锚点+滚动动画

2023-10-30

在这里插入图片描述

目前用的两种方法实现:
第一种:原生js实现
注意:因为移动端可滚动区域可能会嵌套在其他架子下,所以需要用到ref获取滚动区域,
正常获取scrollTop:前者基于html,后者基于body
scrollTop = document.documentElement.scrollTop || document.body.scrollTop
获取指定滚动区域(想要谁滚动就指定谁)
scrollTop = commissionDataMainRef.value.scrollTop
首先div上声明ref
在这里插入图片描述
其次,在setup里
const commissionDataMainRef = ref();
然后return 出去
return { commissionDataMainRef }
最后就可以在js中用
commissionDataMainRef.value.scrollTop

代码如下:

定义导航栏

<ul class="navs">
      <li v-for="(item, index) in indexList" :key="item" :class="{active: state.active===index}" @click="scrollTo(index)" >
        {{item}}
      </li>
</ul>
 indexList.value = ['排名', '极速', '非极速', '退款', '积分']

声明方法

setup(props, { attrs, slots, emit, expose }) {
    const state = reactive({
      active: 0,
      currentActive: null,
      scrollTopLength: 0,
      timer: null
    })
    const commissionDataMainRef = ref()
    let indexList = ref([])
    onBeforeRouteLeave((to, from, next) => {
       window.removeEventListener('scroll', handleScroll)
       next()
    })
    // 提成看板角色判断
    const initCommission = async () => {
      indexList.value = state.commissionType.teamType === '极速' ? ['排名', '极速', '非极速', '退款', '积分'] : ['排名', '非极速', '极速', '退款', '积分']
    }
    initCommission()

    const initData = async () => {
      scrollTo(props.workSpace === 'workSpaceIntegral' ? 4 : 0)
    }
    const handleScroll =  () => {
        // 获取所有锚点元素
      const navContents = document.querySelectorAll('.scrollCommission>div')
      // 所有锚点元素的 offsetTop
      const offsetTopArr = []
      navContents.forEach(item => {
        offsetTopArr.push(item.offsetTop)
      })
      // 获取当前文档流的 scrollTop
      clearTimeout(state.timer)
      state.timer = setTimeout(isScrollEnd, 100);
      const scrollTop = commissionDataMainRef.value.scrollTop
      state.scrollTopLength = scrollTop
      // 定义当前点亮的导航下标
      let navIndex = 0
      for (let n = 0; n < offsetTopArr.length; n++) {
        // 如果 scrollTop 大于等于第n个元素的 offsetTop 则说明 n-1 的内容已经完全不可见
        // 那么此时导航索引就应该是n了
        if (scrollTop >= offsetTopArr[n]) {
          navIndex = n
          // state.currentActive && (state.currentActive.type = false)
        }
      }
      state.active = state.currentActive ? (state.currentActive.type ? state.currentActive.index : navIndex) : navIndex
      // state.currentActive.type = false
    }
    const isScrollEnd  = () => {
      const scrollTop = commissionDataMainRef.value.scrollTop
      if(scrollTop == state.scrollTopLength){
        state.currentActive && (state.currentActive.type = false)
      }
    }
      // 跳转到指定索引的元素
    const scrollTo = (index) => {
      state.active = index
      state.currentActive = {
        type: true,
        index
      }
      // 获取目标的 offsetTop
      // css选择器是从 1 开始计数,我们是从 0 开始,所以要 +1
      const targetOffsetTop = document.querySelector(`.scrollCommission>div:nth-child(${index + 1})`).offsetTop
      // 获取当前 offsetTop
      // let scrollTop = document.documentElement.scrollTop || document.body.scrollTop
      let scrollTop = commissionDataMainRef.value.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
          commissionDataMainRef.value.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
          commissionDataMainRef.value.scrollTop = scrollTop
          requestAnimationFrame(smoothUp)
        }
      }
    }
     // 监听滚动
    nextTick(() => {
      window.addEventListener('scroll', handleScroll, true)
    })

    return {
      state,
      commissionDataMainRef,
      indexList,
      scrollTo
    }
  },

第二种:vant组件的索引栏(比较省事,但自定义不好)
vant索引栏:https://vant-contrib.gitee.io/vant/#/zh-CN/index-bar

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

vue3实现导航栏绑定内容锚点+滚动动画 的相关文章

随机推荐

  • 【time series】时间序列领域的Transformer综述论文笔记

    论文名称 Transformers in Time Series A Survey 论文年份 2022 5 7 论文作者 阿里巴巴达摩院 论文下载 https arxiv org abs 2202 07125 论文源码 https gith
  • 零基础CSS入门教程(8)——CSS设置字体

    本章目录 1 任务目标 2 css设置字体 3 代码演示 4 小结 1 任务目标 我们前几个小结学习了 css的选择器 和及基本的改变字体颜色 我们这一小结学习一下设置字体的一些功能 2 css设置字体 1 font size这个是设置字体
  • Link Cut Tree (动态树)【P3690】

    题目链接 给定n个点以及每个点的权值 要你处理接下来的m个操作 操作有4种 操作从0到3编号 点从1到n编号 0 后接两个整数 x y 代表询问从x到y的路径上的点的权值的xor和 保证x到y是联通的 1 后接两个整数 x y 代表连接x到
  • springboot websocket 传递 头信息 协议头 token 的前后端解决方案

    文章目录 一 前言 二 js websocket 传递token 2 1 基于协议头 三 后台取出websocket协议头的参数 3 1 取出token 3 2 注意大坑 四 结尾 一 前言 关于springboot websocket 可
  • python3 爬虫实战之爬取网易新闻APP端

    一 使用工具 这里使用了火狐浏览器的user agent插件 不懂的可以点这里火狐插件使用 二 爬虫操作步骤 百度 网易新闻并选择 步骤一 步骤二 步骤三 步骤四 最后一步 注意点 1 网易新闻类型 一共是下面的几种 BBM54PGAwan
  • DataSpell学习

    今天刚发现一个有用的数据分析软件DataSpell 下载地址 https www jetbrains com zh cn dataspell features 安装很简单 按照步骤一路来就行了 支持ipynb文件 其实和jupyter no
  • pip3 install命令执行时指定源+指定版本

    1 指定源 用法 pip3 install i https pypi tuna tsinghua edu cn simple 3rd MODULE NAME 例如 pip3 install i https pypi tuna tsinghu
  • Ubuntu下为可执行文件和脚本文件(.sh)生成桌面快捷方式

    1 前言 在Ubuntu中 有些软件是安装的 如deb的安装包 用dpkg i安装 有些软件可能是不需要安装 直接解压tar gz这类文件直接就可以运行了 但是每次运行的时候都要输入一遍命令十分麻烦 因此想把它建个快捷方式放到桌面或启动栏里
  • Segformer网络数据流机制

    代码来源 https github com bubbliiiing segformer pytorch 网络特点 结合了Transformers与轻量级的多层感知机 MLP 解码器 包含一个新颖的分层结构的Transformer编码器 该编
  • Anaconda虚拟环境,更新库

    以管理员身份启动 Anaconda Prompt 1 升级Anaconda前需要先升级conda 升级conda conda update conda 2 升级anaconda conda update anaconda base环境 直接
  • qnap安装Linux程序,[Troy]瞎折腾 篇一:【智能家居】威联通QNAP TS-251A安装Ubuntu+Hassio+Samba经验分享...

    原标题 Troy 瞎折腾 篇一 智能家居 威联通QNAP TS 251A安装Ubuntu Hassio Samba经验分享 Home Assistant是一款基于 Python 的智能家居开源系统 支持众多品牌的智能家居设备 可以轻松实现设
  • win11 vs2019下的qt5.15安装配置

    一 vs2019 先前安装过的版本 在此不做赘述 仅为前提条件 二 qt安装 1 qt版本选择 目前qt更新到6 3 但因为6的版本太新 而5 15是一个LTS长期维护版本 维护期一直到2025年 所以在此选择qt5 15版本 2 qt在线
  • 给Tomcat添加第三方jar包、如何在IDEA中启动部署Web模板

    给Tomcat添加第三方jar包 第一种方式 1 将jar包放到lib目录中 2 将jar包加入到模块中 Add as Library 第二种方式 1 可以打开项目结构菜单项目操作界面 添加一个自己的类库 2 添加你类库需要的jar包 3
  • 美国读研计算机 回国后好就业吗,美国留学归国就业前景如何

    很多在美国留学的小伙伴们都会选择在毕业后回国发展 那么 美国留学归国的就业前景如何呢 感兴趣的小伙伴快来阅读出国留学网的这篇文章吧 希望可以为大家提供参考 美国留学回国就业前景 1 医药领域专业人才和相关人才需求量增加比重最大 其中对应的包
  • LaTex加入新package方法

    1 前几天去 https www ctan org 下载booktabs宏包 下载的文件中没有sty文件 有ins文件 用winedit打开ins文件 用late编译 同一个文件夹中得到了一个sty文件 2 将sty文件拷贝到相应的late
  • numpy--广播及np.shape的案例

    numpy广播 最近有一个小需求 给定 a 0 1 2 M 1 1 1 1 求得 T 0 0 0 0 1 1 1 1 2 2 2 2 经过尝试 终于采用如下代码成功 a reshape 3 1 M reshape 1 4 reshape 3
  • PID算法,计算的是差值,是差值

    typedef struct float Kp 比例系数Proportional float Ki 积分系数Integral float Kd 微分系数Derivative float Ek 当前误差 float Ek1 前一次误差 e k
  • JAVA代码实现抖音转载视频无水印视频,亲测通过

    许多小伙伴想做抖音视频 无奈没有摄影器材 也没有取景材料 就想着去用别人人气视频来提高自己的粉丝量 可问题又来了 别人的视频通过分享 或者链接根本不是原创 上面还带着水印 视频一挂上去就被发现了 小则视频不通过 给出警告 大则封号 降低视频
  • Linux centos8安装docker

    1 下载docker ce的repo curl https download docker com linux centos docker ce repo o etc yum repos d docker ce repo 2 安装依赖 yu
  • vue3实现导航栏绑定内容锚点+滚动动画

    目前用的两种方法实现 第一种 原生js实现 注意 因为移动端可滚动区域可能会嵌套在其他架子下 所以需要用到ref获取滚动区域 正常获取scrollTop 前者基于html 后者基于body scrollTop document docume