• 移动端吸顶方案


    本文介绍三种方式做移动端吸顶,记录不同方式下遇到的问题及思考.

    1-sticky做吸顶

    sticky定位没有导致元素脱离文档流

    sticky失效

    sticky兼容性查询:好用的查询网址

    什么时候,会导致粘贴定位失效呢?(下面这两种是网上已有的)
    1.父级元素设置了overflow:hidden
    2.包裹的最近的父级元素高度小于等于sticky元素的高度会失效

    自己遇到的一个sticky失效原因竟然是双层tab吸顶问题

    在这里插入图片描述

    在这里插入图片描述

    原因:

    第一层tab是手写的样式,第二层tab使用的是ant.design中的tab组件,显然出现问题原因是,第二层tab导致的内容过长出现了滚动条,目前这个sticky定位的父元素是高于sticky元素的,但是定位还是失效了。
    在这里插入图片描述
    在这里插入图片描述

    sticky文字抖动问题

    这是需要在IOS系统上,使用小于100%的比例或者大于100%比例才会出现的问题
    详细见链接视频:
    B站视频

    sticky定位,当使用rem单位时,会出现细线问题

    B站视频

    这个在IOS手机上很明显,在安卓机上,有时能看的出来,细线出现的原因是后面有背景色,rem设置高度的元素不能紧凑的连接起来,而且由于抖动问题,所以细线就此产生

    使用变量控制类名,从而转换样式

    如果ts报错,不能把null赋值给element,
    使用下面这条语句,就能没有ts类型错误

    使用IntersectionObserver对象监听是否吸顶

    useEffect(() => {
        fetch('http://localhost:80/admin/story', {
          method: 'get',
        }).then((response) => response.json())
        .then((res) => {
          // console.log(res.data.rows)
          handlerStory(res.data.rows)
        }).catch((err) => {
          console.log(err, 'error');
        })
        const dom: HTMLElement = watchDOM.current  as unknown as HTMLElement;
        let isVisibility = true;
        const io = new IntersectionObserver(() => {
          isVisibility = !isVisibility;
          setIsTop(isVisibility)
        })
        io.observe(dom);
        return () => {
          io.disconnect();
        }
      }, [])
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    为什么使用类名比使用dom修改样式更好?

    在这里插入图片描述

    chrome 中渲染流水线的流程

    在这里插入图片描述

    一个 html 是怎么被处理成一个页面的。html 中 dom 部分生成 dom tree,css 部分生成 stylesheet,dom tree 在解析完后会等待 stylesheet 构建完再渲染。stylesheet 根据默认样式、样式继承、css 选择器规则、样式优先级等规则,找到对应的 dom 节点赋予它样式,形成 dom 结构+样式的 render tree。其中有些节点是不可见的(不是 opacity: 0,而是诸如 display: none 这样的),它们不会影响其他节点的位置,在渲染时不需要考虑,所以过滤掉这些节点之后生成 layout tree,layout tree 会根据节点之间的相互影响生成它们的位置信息(reflow 回流/重排)。

    dom tree —>stylesheet —> render tree —> 节点是否可见—> layout tree(节点的位置信息)

    你以为到了 layout tree 这一步终于可以渲染了吗,还远没有。layout tree 会根据某些 css 属性分层,比如 position: absolute; position: fixed 等等。如果它们发生更新,不需要连带其他节点 reflow,所以分层有利于单独处理。然后每个图层会生成各自的绘制指令列表(repaint 重绘),很底层的命令,描述了每一个点每一条线如何绘制。

    layout tree —> 分层 ----> repaint–>合成层(优先处理可视区图块)–>biz组件–>显示器的后缓冲区–>前后缓冲区交换,显示下一帧

    gpu绘制:图块的绘制命令会通过光栅化线程池交给 gpu 绘制

    你以为生成了绘制命令终于可以渲染了吗,还远没有。它们会被交给合成层,顾名思义,它是负责将那些图层合并的。它并不会全量的处理整个页面,而是优先处理可见视口附近的图块,如果页面过于复杂,它还会先给出低分辨率的位图。图块的绘制命令会通过光栅化线程池交给 gpu 绘制。合成层拿到 gpu 绘制出来的位图后,将它们合成为一张位图,这就是当前页面。你觉得终于渲染完了吗,并没有。它会将位图交给浏览器进程里的 biz 组件,biz 组件会交给显示器的后缓冲区,当显示器需要显示下一帧之前,前后缓冲区交换,屏幕上终于展示出新渲染的页面帧。(这里补个小知识,requestAnimationFrame 的背后原理就是显示器发送了 sync 信号,渲染进程将 requestAnimationFrame 回调放进消息队列,从而实现了 js 未阻塞的情况下 requestAnimationFrame 可以随帧调用)

    可以发现浏览器想渲染一帧页面要经过如此多的步骤,是不是真为它的性能捏一把汗,这也是 HTML 方便开发带来的代价。我们还可以看出整个流程中最昂贵的步骤就是 reflow 和 repaint 了,至于合成层那边主要是和 GPU 打交道,不会占用渲染线程(也就是执行 js 的线程),并且 GPU 本来就十分擅长处理图片,所以合成层的工作很快。

    因此,性能优化的核心思路其实就是尽可能减少 reflow、repaint 的工作,尽可能多利用合成层的工作。比如 css 硬件加速,包括 transform3D、opacity、willchange 等。拿 transform3D 来说,其实它只是图层的位移、转换,并不影响其他图层,所以不会经过 reflow 和 repaint,直接在合成层处理,GPU 处理这种变换非常快。因此硬件加速技巧可以极大的优化 css 性能。

    下面谈一下滚动操作带来的影响在渲染流水线中的处于什么位置。首先滚动可能会产生滚动条,它的突然出现影响了其他元素的布局位置,会触发 reflow 以及后面的所有流程。滚动过程中,前面说过合成层初始优先处理可见视口附近的图块,其他部分其实还没有处理,元素结构太复杂时滚动过快可能让合成层来不及处理,从而出现白屏区域。还有比如 position: fixed 的元素,会跟着滚动走,那么它也会在滚动中 repaint 的。

    性能对比:

    使用变量+IntersectionObserver+sticky
    在这里插入图片描述

    使用变量+scroll +sticky

    在这里插入图片描述

    使用变量+scroll +sticky+debounce(防抖500ms)
    在这里插入图片描述

    使用dom +scroll +sticky+debounce(防抖500ms)
    在这里插入图片描述

    使用dom +scroll +sticky
    在这里插入图片描述

    2-使用固定定位做吸顶-fixed

    固定定位由于脱离文档流,所以计算监听元素与吸顶元素之间的距离比较难以计算,计算出现误差就会导致页面出现弹跳现象
    fiexd脱离正常文档流

    可以在吸顶的这个时候做样式修改
    不需要在使用父盒子设置高度给吸顶元素做保底
    还是会产生rem细线问题
    但是文字不会产生抖动效果

    脱离文档流后,宽度100%包含了滚动条的宽度

    在移动端由于滚动条很小,所以影响很小,但是还是能够看出来,对不齐了
    在这里插入图片描述

    获取页面内滚动条宽度

    function getScrollbarWidth() {
      if (scrollbarWidth !== null) {
        return scrollbarWidth;
      }
    
      if (typeof document !== 'undefined') {
        const div = document.createElement('div');
        const newStyles = {
          width: '100px',
          height: '100px',
          position: 'absolute',
          top: '-9999px',
          overflow: 'scroll',
          MsOverflowStyle: 'scrollbar',
        };
    
        Object.keys(newStyles).map((style) => {
          // @ts-ignore
          div.style[style] = newStyles[style];
        });
    
        document.body.appendChild(div);
        scrollbarWidth = div.offsetWidth - div.clientWidth;
        document.body.removeChild(div);
      } else {
        scrollbarWidth = 0;
      }
    
      return scrollbarWidth || 0;
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    B站视频

    fixed吸顶元素与监听元素的距离,监听元素高度过高,会导致内容跳动,高度过低,会导致吸顶元素与内容脱轨

    3-使用内容fiexd,达到吸顶效果

    当页面出现两个滚动条时,滚动触发时机无法掌控

    设置overflow:scroll属性的元素,一定要设置高度,不然无法产生滚动条

    可能第一个滚动条滚动到底,才开始滚动第二个滚动条,也可能第一个滚动条滚动一半,开始滚动第二个滚动条,还可能先滚动第二个滚动条,第一个滚动条不滚动,取决于鼠标所在位置.

    鼠标在滚动第一个滚动条时,由于页面滚动,鼠标处于第二个滚动元素上面,如果此刻鼠标移动了,第二个滚动条开始滚动, 第二个滚动条滚动完,如果第一个滚动条还有未滚动的位置,第一个滚动条继续滚动;–1

    如果鼠标不移动,第一个滚动条滚动,滚动完成之后,第二个滚动条不会滚动;----2

    鼠标如果在第一个产生滚动的元素上面,只滚动第一个滚动条;----3

    如果鼠标位于第二个产生滚动元素身上,则只有第二个元素滚动,第一个滚动条不滚动;----4

    B站视频

    所以争对上面的效果,内容fixed无法达到效果,
    不过如果是tab固定定位,这样实现效果也很好
    在这里插入图片描述

    参考资料:
    https://mp.weixin.qq.com/s/hFG1ypsEckVIZb5OCv0H7g
    https://www.hongkiat.com/blog/writing-better-css/

  • 相关阅读:
    【GIT】解决合并冲突完整流程(带图及步骤)
    dubbo:从零理解及搭建dubbo微服务框架(一)【附带源码】
    大型网站系统架构演化实例_5.使用反向代理和CDN加速网站响应
    (二)ndarray(Python)与Mat(C++)数据的传输
    RTL8380M/RTL8382M管理型交换机系统软件操作指南二:转发表
    goroutine之间如何正确的共享变量,顺序一致性内存模型,happens before
    深度学习基础知识 Batch Normalization的用法解析
    螺旋矩阵||真的很有趣!(蓝桥杯宝贝们看过来)
    Vue解决导出pdf文件图片展示不全问题
    Redis对象的数据结构及其原理汇总
  • 原文地址:https://blog.csdn.net/qq_44859233/article/details/126088596