Vue3从0到1组件开发-基础组件:BackTop回顶

1,224 阅读3分钟

这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战

基础组件最后一件:Backtop

回到顶部的野望

谈及前端开发中的基础交互,必不可少的一个功能应该就是回到顶部了吧,

但是Backtop回到顶部功能应该也是网页中最不起眼的一个功能了,这句话没争议吧。

在我为数不多的开发经验当中,看过好几款不同的回到顶部,如瞬间回到顶部滚动回顶顶部定时回到顶部这几种算是比较常见的了,其中尤以瞬回,滚回这两种方式最为常见,而定时回顶则相对少一些,实现略微有点复杂,收益也不大,也就是传说中的付出大于回报。

当然这些都是看个人意愿,而在常规的Web项目开发中,回到顶部大概是必不可少的啦,尤其是长页面的项目中。

基础组件这一块也就以这个组件来作为结尾,之后开始下一个分类的组件分享。

画虎先画骨。

这里还是先从结构讲起,回到顶部的结构比较简单,常规布局就可以,主要是通过一个值控制好它的显示隐藏就可以了。

<template lang="pug">
block content
div(
  class="yx-backTop"
  :style="{right: `${right}px`, bottom: `${bottom}px`}"
  @click="toTop"
  v-show="backTop" // 控制是否显示,这里切忌用v-if,属于一个小小小的优化。
)
  slot
    div.yx-backTop-content
      <yx-icons type="backTop" />
</template>

结构比较简单,如果传值就显示传入样式,否则显示一个单纯的图标,默认样式也可以自定义一个啦。

逻辑部分

通过结构部分,就可以很清晰看到接受的传值了,那么这里只讲一下核心的内容,即定时回到顶部的方法。

这个方法并非我自己写的,本来只是想用常规的滚动回顶的,但是思来想去,那样的话这个组件就没什么好些的了。所以经过我多方查阅,来回闹腾,终于在其他的组件库找到了类似的方法,所以这里只是简单的进行一波分析。

代码如下


onMounted(() => {
  window.addEventListener('scroll', handleScroll, false)
  window.addEventListener('resize', handleScroll, false)
})

onBeforeUnmount(() => {
  window.removeEventListener('scroll', handleScroll, false)
  window.removeEventListener('resize', handleScroll, false)
})

const handleScroll = () => {
  backTop.value = window.pageYOffset >= props.showHeight;
}
const toTop = () => {
  const sTop = document.documentElement.scrollTop || document.body.scrollTop;
  scrollTop(window, sTop, 0, props.duration);
  emits('click');
}

const scrollTop = (el, from = 0, to, duration = 500, endCallback) => {
  if (!window.requestAnimationFrame) {
    window.requestAnimationFrame = (
      window.webkitRequestAnimationFrame ||
      window.mozRequestAnimationFrame ||
      window.msRequestAnimationFrame ||
      function (callback) {
          return window.setTimeout(callback, 1000/60);
      }
    );
  }
  const difference = Math.abs(from - to);
  const step = Math.ceil(difference / duration * 50);

  function scroll(start, end, step) {
    if (start === end) {
        endCallback && endCallback();
        return;
    }

    let d = (start + step > end) ? end : start + step;
    if (start > end) {
        d = (start - step < end) ? end : start - step;
    }

    if (el === window) {
        window.scrollTo(d, d);
    } else {
        el.scrollTop = d;
    }
    window.requestAnimationFrame(() => scroll(d, end, step));
  }
  scroll(from, to, step);
}

核心方法就是这里的window.requestAnimationFrame了, 正好前不久以为掘金大佬写过相关的文章# 一个神奇的前端动画 API requestAnimationFrame

简单来说,就是requestAnimationFrame是一个不断重复执行的函数,会一直绘制屏幕,而这个函数要做的就是计算出要滚动的距离,以及每次执行时滚动的距离。

整个函数入口判断该API是否可用,之后计算当前滚动距离 减去 目标距离, 得出需要滚动的距离, 之后在计算每次执行时要滚动多少距离const step = Math.ceil(difference / duration * 50); 剩下的就是细化这个函数了。

到这就是整个核心函数要做的事情了。

其他的样式及结构是非常个性化的东西,就不去过多的强调我的做法了。

最后

截止到本文结束,已经是写完了这个组件库中大部分的基础组件,并且自认为基础的一些内容是都涵盖在文中,能满足其他任何类型(包括我没写过)的组件开发了。

那么从下文开始,就将正式进入到下一大类的组件分享了。敬请期待吧。

最后,在这里列一下基础组件列表:

Button按钮

Mask遮罩

Icon图标

Link