美文网首页
Vue 导航栏固定在顶部,锚点内容绑定(双向),监听滚动事件,平

Vue 导航栏固定在顶部,锚点内容绑定(双向),监听滚动事件,平

作者: 前端小猪仔 | 来源:发表于2021-01-15 14:25 被阅读0次

    最近给营销市场部做了个H5页面,页面大概要求就是一个单独的H5页面,顶部导航栏固定含有三个导航按钮必须和正文对应内容联动。
    首先想到需要用到锚点,但是单纯的锚点功能会显得滚动条很突兀一下子就跳到内容区了,效果很不理想,然后单纯的一个H5页面去引进jQuery库肯定也是不合理的,所以必须自己去监听滚动条实现功能。

    1.首先按照要求固定头部导航栏 导航栏
    <div class="header-main" :style="getColor()">
        <div class="h5-header">
            <div class="header-left"><i class="okicon icon-0121"></i></div>
            <div class="header-right">
                <span :class="{active: active == 0}">OKKONG OS</span>
                <span :class="{active: active == 1}">系统亮点</span>
                <span :class="{active: active == 2}">联系客服</span>
            </div>
         </div>
    </div>
    

    固定导航栏css
    其中有个小细节就是因为大div里设置了背景图,导航栏的背景色要求是设置成0.15,这个时候我们背景色应该使用rgba,第四个参数写上透明度0.15(小本本记好),这个就可以解决以后背景图和背景色需要同时存在的情况了

    .header-main{
        min-width: 1200px;
        background:rgba(255, 255, 255, 0.15);
        position: fixed;
        top:0;
        left: 0;
        right: 0;
      }
    

    设置选中导航按钮的样式

    .active{
            color: #FFA624;
            border-bottom: 4px solid #FFA624;
            font-weight: 800;
          }
    

    初始data里active值为0,默认选中第一个导航按钮

    data(){
        return {
          active: 0, // 当前激活的导航索引
          scrollTop:'',//滚动距离
        }
    }
    

    接下来我们就需要监听滚动事件handleScroll()

    handleScroll () {
          const scrollTop = document.documentElement.scrollTop || document.body.scrollTop//获取滚动距离
          this.scrollTop = scrollTop//data里return了一个全局的scrollTop
          console.log(scrollTop)
          //这边距离我是通过打印scrollTop大致自己粗略的计算了下,用来判断滚轮滚动相应的距离改变导航栏对应菜单样式
          if (scrollTop > 1115) {
            this.active = 1
          }
          if(scrollTop > 1850){
            this.active = 2
          }
          if(scrollTop < 1000){
            this.active = 0
          }
        }
    

    顶部导航栏还有个样式就是需要滚动下去时改变导航栏背景色,这个时候我们就需要给导航栏添加动态的style样式

    <div class="header-main" :style="getColor()">
    

    样式方法

    getColor(){
          //当滚动距离超过导航栏高度时改变背景色
          if(this.scrollTop > 45){
            return {
              background:"#487DFE"
            }
          }else{
            return false
          }
        }
    

    最重要的一个环节就是给导航菜单栏添加点击滚动事件scrollTo()

    给三个导航按钮增加点击事件

    <div class="header-right">
           <span :class="{active: active == 0}" @click="scrollTo(1)">OKKONG OS</span>
           <span :class="{active: active == 1}" @click="scrollTo(2)">系统亮点</span>
           <span :class="{active: active == 2}" @click="scrollTo(3)">联系客服</span>
     </div>
    

    定义scrollTo()方法

    具体需要注意的地方和相应的解释在代码中已经给出

    //跳转到指定元素
        scrollTo(val){
          // 定义一次跳 50 个像素,数字越大跳得越快,但是会有掉帧得感觉
          const STEP = 50
          let scrollTop = document.documentElement.scrollTop || document.body.scrollTop//获取滚动距离
          var targetOffsetTop = ''
          if(val == 1){
            targetOffsetTop = document.querySelector('.h5-os').offsetTop - 60//获取指定元素视口距离
          }
          if(val == 2){
            targetOffsetTop = document.querySelector('.h5-oslight').offsetTop - 60//获取指定元素视口距离
          }
          if(val == 3){
            targetOffsetTop = document.querySelector('.contactService').offsetTop - 60//获取指定元素视口距离
          }
          if (scrollTop < targetOffsetTop) {
            // 往下滑
            smoothDown()
            console.log(targetOffsetTop,'视口距离')
          }else{
            console.log(targetOffsetTop,'targetOffsetTop')
            smoothUp()
          }
          // 定义下滑函数
          function smoothDown() {
            console.log(scrollTop,'scrollTop')
            // 如果当前 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 的函数
              // 关于 requestAnimationFrame 可以自己查一下,在这种场景下,相比 setInterval 性价比更高
              requestAnimationFrame(smoothDown)
            }
          }
          // 定义上滑函数
          function smoothUp() {
            // 如果当前 scrollTop 大于 targetOffsetTop 说明视口已经滑过指定位置需要上滑
            if (scrollTop > targetOffsetTop) {
              // 如果和目标相差距离大于等于 STEP 就跳减去 STEP
              // 否则直接跳到目标点,目标是为了防止跳过了。
              if (scrollTop - targetOffsetTop >= STEP) {
                scrollTop -= STEP
              } else {
                scrollTop = targetOffsetTop
              }
               document.body.scrollTop = scrollTop
               document.documentElement.scrollTop = scrollTop
              // 屏幕在绘制下一帧时会回调传给 requestAnimationFrame 的函数
              // 关于 requestAnimationFrame 可以自己查一下,在这种场景下,相比 setInterval 性价比更高
              requestAnimationFrame(smoothUp)
            }
          }
        },
    

    最后在mounted()中监听滚动事件,代码如下

    mounted() {
        // 监听滚动事件
        // document.getElementById("blockmain").addEventListener("scroll", this.handleScroll)
        // window.addEventListener('scroll', this.handleScroll)
        this.$nextTick(function () {
          window.addEventListener('scroll', this.handleScroll)
        })
      },
    

    需要注意的是在组件销毁时我们需要移除滚动监听器,不然监听器会报错

    destroy() {
        // 必须移除监听器,不然当该vue组件被销毁了,监听器还在就会出错
        window.removeEventListener('scroll', this.handleScroll)
      }
    

    以上便是此次滚动事件平滑滚动和锚点双向功能的实现逻辑

    相关文章

      网友评论

          本文标题:Vue 导航栏固定在顶部,锚点内容绑定(双向),监听滚动事件,平

          本文链接:https://www.haomeiwen.com/subject/smnxaktx.html