一个div压在另一个div上面_我给 Chromium v84 提了一个 bug

本文讲述了在 Chrome v84 版本中,`div`元素加载更多内容时出现滚动偏移的问题,该问题影响用户体验。作者通过排查发现是 Chromium 的一个bug,影响范围包括Chrome、Edge等浏览器。文章提供了两种解决方案:1) 记住滚动位置并在内容加载后回滚;2) 隐藏加载按钮来避免偏移。同时,作者还探讨了模拟此行为的可能性和移动端的相似场景。
摘要由CSDN通过智能技术生成

背景

我们的网站有个「点击加载更多」的功能,就像这样

5de34fe0158bbd3bc7c0d9bb1643244f.gif

点击按钮,拉取数据填充列表,用户自行滚动到下方,继续点击加载更多……

这种场景是不是很常见??我浏览了几个网站,都有这种场景,国内最流行的 Ant Design 组件库更是直接封装了这个功能[1]

本来只是没啥问题的,直到 Chrome V84 的出现…

确切的说,是 chromium 84 出了问题,因为最新的 edge 用的 chromium 内核,也出了相同的问题

有一天,收到用户反馈:在点击加载更多后,列表内容像是原地刷新,体验实在不在,就像这样

728921d02febca86df7cae1772d48b39.gif

在线体验链接,需要 Chrome 84 哦>[2]

点击加载更多,按钮位置始终不变,列表填充后自行向上滚动 ?

看这个 gif 你可能觉得还行,真实场景是会加载更多内容的,这种自行滚动会让用户突然找不到刚刚浏览项的位置,极大破坏用户体验。

或者说,这种做法有一定场景,但是行为控制应该交给前端开发者来定不是?

(废话好像有点多,想看解决方案的直接拉到文末~

怎么发现是 chromium 的 bug/feature ?

收到的反馈,说的是偶现,然后部分用户高频出现。所以我一开始并没有往浏览器层面想,而是自己的代码有没有逻辑漏洞。

在几个浏览器上跑了一遍,发现确实有些浏览器能复现。在确认自己代码天衣无缝之后,我怀疑起了 react ?

为了验证和框架无关,我关闭了 JavaScript ,手动复制列表元素到父节点,还是能够稳定复现。。为了严谨,自己又用原生代码写了一个 demo[3] ,还是能够复现。那么问题就出在这些浏览器身上了。。

这一晚搞到了 11 点多,先回去睡个觉。。

第二天醒来,脑子清醒多了。

先确定复现浏览器的版本,同事装的 Chrome 83 没问题,而自己的 84 出了问题,看来是这次 Chrome 更新的锅。

接着去网络上搜搜有没有人遇到类似的问题。恰好,前一天也有个网友遇到了同样的问题,见 给你代码:chrome84 追加元素的问题[4]

最后去看下更新文档(在此之前我只知道 Chrome 84 调整了 same-site 策略

在 Chrome 84 新特性[5] 文中,并没有提到这个功能。

看来对于官方来说,这种功能改动是很小的,不足以放到 feature 列表中 ?,更多细节提示需要到 commit log 里查看

看来只能去版本提交日志[6]里查下了,在输入了 scroll 关键字后,跳出来的结果有数千条,着实劝退,我还是去提 bug[7] 等待官方解答吧。

影响范围

目前使用 chromium 84 内核的浏览器都受到了影响,包括:

  1. Chrome 84
  2. Edge 84
  3. Android Chrome 84
  4. Android Webview (默认跟随本地 Chrome 升级而升级,也可以独立维护版本)

啥,没有 iOS ? 因为 iOS 的 Chrome 用的不是 chromium 内核 ?

滚动偏移重置的解决方案

既然浏览器做了滚动,那我们「记住上次滚动位置,加载完后滚回去」不就行了?

试了一下,还真的有效。

完整代码:

html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <style>.container { width: 100%;display: flex;flex-direction: column;align-items: center;
        }.items { width: 100%;
        }.item { margin-top: 10px;height: 100px;width: 100%;background-color: #FF142B;
        }.btn { width: 200px;height: 44px;margin-bottom: 40px;background: #BCCFFF;box-shadow: 0 0 3px 0 rgba(0, 0, 0, 0.05);border: none;border-radius: 22px;font-size: 15px;font-weight: 500;color: #FF142B;-webkit-transition: 150ms all;transition: 150ms all;
        }style>
    <script>function genRandomColor() { const fn = () => parseInt(Math.random() * (255 + 1), 10)return `rgb(${fn()},${fn()},${fn()})`
        }function showMore() { let items = document.querySelector('.items')let tmp = document.createElement('div')// 记住当前位置const currentScrollTop = document.documentElement.scrollTop || document.body.scrollTop
            tmp.className = "item"
            tmp.style = `background-color: ${genRandomColor()}`;
            items.appendChild(tmp)// 滚回到之前位置window.scrollTo({ top: currentScrollTop
            })
        }function showMoreWithTimeout(){
            setTimeout(showMore,10)
        }script>
head>

<body>
    <div class="container">
        <div class="items">
            <div class="item">div>
            <div class="item">div>
            <div class="item">div>
            <div class="item">div>
            <div class="item">div>
            <div class="item">div>
            <div class="item">div>
            <div class="item">div>
        div>
        <button class="btn" onclick="showMore()">点击展开更多button>
    div>

body>

html>

虽然可以了,但还是会有以下几个疑问:

  1. Chrome 84 内部滚动的时机是什么时候?
  2. 一次事件循环中多次执行 scrollTo ,会发生什么情况?
  3. 已经执行了 scrollTo ,在 setTimeout 里执行 scrollTo 和在 rAF 里执行 scrollTo ,有什么区别?
  4. scrollTo 和 scrollBy 同时执行,会发生什么情况?

问题 1 比较复杂,先看其他几个问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值