技术博客

越是喧闹,越是孤独。越是寂寞,越是丰富
The more noisy, the more lonely. The more lonely, the more rich

越是喧闹,越是孤独。越是寂寞,越是丰富
The more noisy, the more lonely. The more lonely, the more rich

技术博客


一个简单的Vue置顶组件的开发

2022-09-18 Mendel
Vue

 麻雀虽小,五脏俱全


很多比较长的页面,例如文章正文页、商品列表页等,当向下滑动到一定距离之后,通常会在侧面等某个位置出现一个可以返回顶部的按钮。本站的文章正文页面近期也增加了此功能。这里就来介绍一下这个置顶组件的开发过程。





01

图标与样式


首先选一个自己喜欢的置顶图标,可以从各大网站上去搜索,也可以自己DIY。我通常会从 iconfont.cn (阿里巴巴矢量图标库) 这个网站上搜索我想要的图标。比如搜索“置顶”就会有很多结果可供选择。


选好图标后,设置尺寸和颜色,可下载PNG或SVG格式,根据需要可放在自己的项目中通过webpack的相关loader加载,也可使用外部链接的方式。我这里使用的是后者,将图标上传到服务器上,然后通过URL的方式访问。为了减少图片体积,优化加载性能,建议使用TinyPNG(tinypng.com)对png或jpeg类型的图片先进行压缩后再使用。



样式方面,我采用了bootstrap风格的button按钮结合icon图片实现置顶按钮的绘制。代码如下(部分样式省略):

<button type="button" class="btn btn-success">  <img src="https://static.mengchen.cc/images/go-top.png" class="img-fluid"></button>




02


置顶功能


置顶按钮的主要功能就是返回页面顶部,通常有两种方法可以实现。

第一种:使用 scrollIntoView API,并通过behavior:'smooth'实现平滑滚动。

document.documentElement.scrollIntoView({ behavior: "smooth" });

第二种:使用jQuery animate API 设置scrollTop:0, 也可以实现动画效果

$('html,body').animate({scrollTop: 0})

我推荐第一种方式,从CanIUse(caniuse.com)上查询scrollIntoView这个功能,主流浏览器都已经支持了,可以放心使用。

第二种方式兼容性更好,但依赖jQuery库,虽然bootstrap 4.x仍然还依赖jQuery,但要注意官网推荐引入的jquery版本是jquery.slim.min.js,而它里面是不包括animate这个功能的,需要更换jquery的全功能版本。现在Bootstrap 5已经移除了对jQuery的依赖,后续本站会考虑升级到Bootstrap 5.x版本,所以现阶段尽量不额外引入jquery的代码,尽量使用原生DOM+Vue来实现功能。



03


显隐控制


置顶按钮需要在页面滚动过一定的距离后才显示,低于这个距离会自动隐藏,所以需要监听scroll事件来控制按钮的显示和隐藏。

window.addEventListener('scroll', event => {  let scrollTop = document.documentElement.scrollTop || document.body.scrollTop  this.visible = (scrollTop > this.threshold)})

其中,visible是控制显示隐藏的布尔变量,可通过v-show绑定到按钮上,threshold是滚动距离分界线,为了可扩展,我将其定义成了组件的props

props: {    threshold: {        type: Number,        default: 1500    }}


要注意的是,既然这是一个组件,就需要考虑组件的生命周期,我们在组件加载时给window绑定了scroll事件,就不要忘记在组件销毁时进行解绑:

beforeUnmount() {    window.removeEventListener('scroll', this.scrollHandler)}

所以前面说的那个eventHandler需要赋值给一个变量(例如scrollHandler),用于组件销毁时的解绑。


如果觉得按钮直接显示/隐藏太单调,那么可以给它加上动画效果,可参考Vue的Transition过渡相关API进行动画设置即可,本站目前实现的效果是从侧边划入划出,代码为:

.move-enter-active, .move-leave-active {    transitiontransform 0.5s ease;}
.move-enter-from.move-leave-to {    transformtranslateX(60px);}

最后,组件的template部分的代码就变为:

<transition name="move">      <div v-show="visible">          <button type="button" @click="goTop">              <img src="...">          </button>      </div></transition>



04


性能优化


细心的小伙伴可能会对scroll事件比较敏感,没错,它的触发频率太高,一秒可达几十次,如果获取scrollTop的值本身需要耗费较多的资源,那么在scroll事件中频繁调用可能会带来一定的性能问题。所以,这里可以考虑使用节流(throttle)功能,将高频的行为转化为低频的行为,也就是降低判断置顶按钮显隐的频率。


我们可采用lodash的throttle函数来实现此功能,可根据自己的需要设置一个interval间隔时间来控制频率:

const scrollHandler = lodash.throttle(() => {    let scrollTop = document.documentElement.scrollTop || document.body.scrollTop    this.visible = (scrollTop > this.threshold)}, 300)
window.addEventListener('scroll', scrollHandler)

需要安装lodash库

npm install lodash --save

与节流(throttle)对应的另一个概念叫做去抖(debounce),可以将高频行为转化到只在最后一次执行,也有很广泛的应用场景,例如在本站搜索页面的输入框中,在输入行为停止后500ms才去执行搜索,这个就是运用了去抖来降低对服务端的压力。关于节流和去抖,大家可以另行查阅其他相关资料深入学习。