越是喧闹,越是孤独。越是寂寞,越是丰富
The more noisy, the more lonely. The more lonely, the more rich
越是喧闹,越是孤独。越是寂寞,越是丰富
The more noisy, the more lonely. The more lonely, the more rich
“ 麻雀虽小,五脏俱全”
很多比较长的页面,例如文章正文页、商品列表页等,当向下滑动到一定距离之后,通常会在侧面等某个位置出现一个可以返回顶部的按钮。本站的文章正文页面近期也增加了此功能。这里就来介绍一下这个置顶组件的开发过程。
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 {
transition: transform 0.5s ease;
}
.move-enter-from, .move-leave-to {
transform: translateX(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才去执行搜索,这个就是运用了去抖来降低对服务端的压力。关于节流和去抖,大家可以另行查阅其他相关资料深入学习。