简介
一天 30 秒 一段代码 一个场景
在 大家一起被捕吧 中刚写了:
在日常开发中我们往往会从用户那获得各种输入, 例如搜索框, 评论框, 文章内容等等.
结果在 segmentfault 阅读评论时看到了一个链接一点直接把我给滚动到顶部, 顿时心中一阵 惨叫双手捶胸 后把页面拉回评论并打开了 控制台 查看了链接为何方神圣:
<a href="#">...</a>
顿时又是一阵 惨叫双手捶胸 原来 segmentfault 评论是支持 Markdown 语法的, 如果再评论里输入 [...](#) 则会被转换成如上代码.
好奇心突发跑到了 掘金 测试了一下带连接的评论, 打开 控制台 看了看由于使用了 target="_blank" 没有出现被传送到顶部的情况, 心里暗暗道 喵哉 以后还是得小心行事, 碰巧每日 30 秒正愁不知道写什么那就来写写 回到顶部 吧.
回到顶部
第一种写法就介绍一下今天被中全套的代码, 利用了 锚点 来实现回到顶部:
<a href="#" 回顶部 ></a>
如果需要滚动到别的元素可以使用 id 属性配合 锚点 来实现:
- <header id="header">
- 我是头部
- </header>
- <a href="#header">
- 回到页面头部
- </a>
不过由于这种方法 滚动 得太快了, 性能肯定是很好就是体验不怎么好. 不过我们可以使用 CSS 的 scroll-behavior 属性来提升体验:
- html, body {
- scroll-behavior: smooth;
- }
虽然第一种方法配合 CSS 的 scroll-behavior 属性显得挺不错, 但是 scroll-behavior 兼容性挺不高的具体可以看 https://caniuse.com/#search=scroll-behavior .
迴到顶部
由于在页面垂直滚动过程中会改变 Windows.scrollY 的值, 第二种便是写法利用 Windows.scrollTo() 把它设置为 0 来实现回到顶部:
Windows.scrollTo(0, 0)
不过这样使用也会导致 滚动 得太快带来的体验不好, 这个时候我们可以利用 Windows.requestAnimationFrame() 告诉浏览器 -- 你希望执行一个动画, 并且要求浏览器在下次重绘之前调用指定的回调函数更新动画, 该方法需要传入一个回调函数作为参数, 该回调函数会在浏览器下一次重绘之前执行.
这里使用里一个来判断当页面没有滚动到顶部时循环调用 Windows.requestAnimationFrame 来进行逐步滚动, 每次滚动的距离 c - c / 8 随着 c 的减小而减小进而实现滚动效果:
- const scrollToTop = () => {
- const c = document.documentElement.scrollTop || document.body.scrollTop;
- if (c> 0) {
- Windows.requestAnimationFrame(scrollToTop);
- Windows.scrollTo(0, c - c / 8);
- }
- };
不过继续查阅 https://caniuse.com/#search=requestAnimationFrame 中的 Windows.requestAnimationFrame() 在主流浏览器中支持挺好的, 但是需要兼容 ie6-9 的同学就得另外寻找方法了. 仔细想想 Windows.requestAnimationFrame() 跟 setTimeout() 好像有点相似.
Windows.requestAnimationFrame 回调函数执行次数通常是每秒 60 次即一秒 60 帧, 将 setTimeout 执行的频率也设置为一样的就行了:
- if (!Windows.requestAnimationFrame) {
- Windows.requestAnimationFrame = function (callback) {
- return setTimeout(callback, 1000 / 60);
- }
- }
- const scrollToTop = () => {
- const c = document.documentElement.scrollTop || document.body.scrollTop;
- if (c> 0) {
- Windows.requestAnimationFrame(scrollToTop);
- Windows.scrollTo(0, c - c / 8);
- }
- };
搞定神器 ie6-9 的兼容问题.
囬到顶部
- document.querySelector('body')
- .scrollIntoView({
- behavior: 'smooth',
- block: 'start',
- })
- let scrollToTop;
- if (Windows.getComputedStyle && Windows.getComputedStyle(document.body).scrollBehavior) {
- scrollToTop = () => document.querySelector('body')
- .scrollIntoView({
- behavior: 'smooth',
- block: 'start',
- });
- } else {
- if (!Windows.requestAnimationFrame) {
- Windows.requestAnimationFrame = function (callback) {
- return setTimeout(callback, 1000 / 60);
- }
- }
- scrollToTop = () => {
- const c = document.documentElement.scrollTop || document.body.scrollTop;
- if (c> 0) {
- Windows.requestAnimationFrame(scrollToTop);
- Windows.scrollTo(0, c - c / 8);
- }
- };
- }
来源: https://juejin.im/post/5c93f9795188252d7e34de65