美文网首页
Vue导航栏吸顶切换功能实现

Vue导航栏吸顶切换功能实现

作者: 小小鱼yyds | 来源:发表于2020-11-27 14:29 被阅读0次

  Vue导航栏吸顶切换功能实现,兼容px2rem-loader自动转rem
最上面的ad-show在实际项目中可以用来做商品或者广告轮播,下面
设置了三个区域块,分别为onePage,twoPage和threePage,在实际项目中可以用作商品详情,物流说明,注意事项等。
  在阅读代码之前,感兴趣的童鞋可以先了解一下clientHeight、offsetHeight、scrollHeight、offsetTop、scrollTop的区别。这样才能明白代码的计算方式和获取元素节点高度的方式。
  附上他人博客链接,写的不错,可以提前阅读一下帮助理解此篇内容:https://blog.csdn.net/qq_35430000/article/details/80277587
   如果木有时间阅读,木有关系,我大概总结了一下:

  • 网页可见区域高:document.body.clientHeight
  • 网页正文全文高:document.body.scrollHeight
  • 网页可见区域高(包括边线的高):document.body.offsetHeight
  • 网页被卷去的高:document.body.scrollTop
  • 屏幕分辨率高:window.screen.height
  • 节点高度(包含padding和border):this.$refs.scrollTwo.offsetTop
  • 节点高度(包含padding,但不包含border):this.$refs.scrollTwo.clientHeight
    严谨起见,我采用了offsetTop来获取节点自己的高度
    因为高度都是动态获取的元素高度,所以不必担心项目用了px2rem-loader把px都自动转成了rem


    微信图片_20201127143453.jpg
<template>
  <div id="needscroll" class="hello">
    <div class="ad-show">
      <p>展示图</p>
    </div>
    <div class="onePage" ref="scrollOne">区域一</div>
    <div class="twoPage" ref="scrollTwo">区域二</div>
    <div class="threePage" ref="scrollThree">区域三</div>
    <div class="home-menu" ref="menuHome" v-if="showMenu">
      <p :class="{ active: active === 1 }" @click="changeActive(1)">区域一</p>
      <p :class="{ active: active === 2 }" @click="changeActive(2)">区域二</p>
      <p :class="{ active: active === 3 }" @click="changeActive(3)">区域三</p>
    </div>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  data() {
    return {
      active: 1,
      rememberScroll: 0,
      showMenu: false,
      scroll1: 0,
      scroll2: 0,
      scroll3: 0,
      isScroll: false,
      menuHeight: 0,
    };
  },
  methods: {
    getScroll() {
      let scrollTop =
        window.pageYOffset ||
        document.documentElement.scrollTop ||
        document.body.scrollTop;
      let scrollT1 = this.$refs.scrollOne.offsetTop;
      this.scroll1 = scrollT1;
      let scrollT2 = this.$refs.scrollTwo.offsetTop;
      this.scroll2 = scrollT2;
      let scrollT3 = this.$refs.scrollThree.offsetTop;
      this.scroll3 = scrollT3;
      //这里之所以加了一层判断,是因为menuHome刚开始为隐藏状态,$refs获取为undefined
      if (this.$refs.menuHome) {
        let space = this.$refs.menuHome.scrollHeight;
        if (scrollTop >= scrollT1 - space - 10) {
          this.showMenu = true;
        } else {
          this.showMenu = false;
        }
      } else {
        if (scrollTop >= scrollT1 - 60) {
          this.showMenu = true;
        } else {
          this.showMenu = false;
        }
      }
    },
    changeActive(val) {
      this.isScroll = true;
      this.active = val;
      let scrolly = 0;
      let space = this.$refs.menuHome.scrollHeight;
      if (val === 1) {
        scrolly = this.scroll1 - space;
      } else if (val === 2) {
        scrolly = this.scroll2 - space;
      } else {
        scrolly = this.scroll3 - space;
      }
      //这里之所以不用这个方法,是因为真机没有动画效果,但在PC浏览器是有的
      // window.scrollTo({
      //   top: scrolly,
      //   behavior: "smooth",
      // });
      this.smoothScroll(0, scrolly, 500);
    },
    smoothScroll(endX, endY, duration) {
      let startX = window.scrollX || window.pageXOffset,
        startY = window.scrollY || window.pageYOffset,
        distanceX = endX - startX,
        distanceY = endY - startY,
        startTime = new Date().getTime();

      // Easing function
      let easeInOutQuart = function (time, from, distance, duration) {
        if ((time /= duration / 2) < 1)
          return (distance / 2) * time * time * time * time + from;
        return (-distance / 2) * ((time -= 2) * time * time * time - 2) + from;
      };

      let timer = window.setInterval(function () {
        let time = new Date().getTime() - startTime,
          newX = easeInOutQuart(time, startX, distanceX, duration),
          newY = easeInOutQuart(time, startY, distanceY, duration);
        if (time >= duration) {
          window.clearInterval(timer);
        }
        window.scrollTo(newX, newY);
      }, 1000 / 60); // 60 fps
    },
  },
  mounted() {
    window.addEventListener("scroll", this.getScroll);
  },
  destroyed(){
      //不要忘记移除掉监听,否则跳转到其他页面会报错的
    window.removeEventListener('scroll',this.getScroll)
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
.hello {
  .ad-show {
    width: 100%;
    height: 200px;
    display: flex;
    justify-content: center;
    align-items: center;
    background: crimson;
  }
  .onePage {
    width: 100%;
    height: 500px;
    text-align: center;
    background: palegoldenrod;
  }
  .twoPage {
    width: 100%;
    height: 400px;
    text-align: center;
    background: powderblue;
  }
  .threePage {
    width: 100%;
    height: 400px;
    text-align: center;
    background: peachpuff;
  }
  .home-menu {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 50px;
    background: white;
    z-index: 999;
    display: flex;
    flex-direction: row;
    p {
      flex: 1;
      height: 50px;
      text-align: center;
      line-height: 50px;
      font-size: 14px;
    }
  }
  .active {
    color: lightsalmon;
    background: rgb(247, 247, 247);
  }
}

我本来想实现滑动到每个区域时,导航栏会自动选择某个区域,但是在scroll的监听方法里面写,快速点击时会产生交叠问题,此功能还会后续优化,有好想法的童鞋欢迎提出你的宝贵意见,以帮助我更好的完善这个功能

相关文章

网友评论

      本文标题:Vue导航栏吸顶切换功能实现

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