likes
comments
collection
share

我的天!居然国内所有react组件库都有这个bug!

作者站长头像
站长
· 阅读数 21

前言

首先声明,没有标题党哈!

以下我知道的国内知名react组件库全部都有这个bug,你们现在都能去复现,一个提pr的好机会就让给你们了,哈哈!复现组件库:

本来字节还有一个semi design,结果我发现它没有Affix组件,也就是固钉组件,让他躲过一劫,他有这个组件我也觉得肯定会复现相同的bug。

Affix组件是什么,以及bug复现

Affix组件(固钉组件)能将页面元素钉在可视范围。如下图:

我的天!居然国内所有react组件库都有这个bug!

这个button组件,会在距离顶部80px的时候会固定在屏幕上(position: fixed),如下图:

我的天!居然国内所有react组件库都有这个bug!

如何复现bug

你在这个button元素任意父元素上,加上以下任意style属性

  • will-change: transform;
  • will-change: filter;
  • will-change: perspective;
  • transform 不为none
  • perspective不为none
  • 非safari浏览器,filter属性不为none
  • 非safari浏览器,backdrop-filter属性不为none
  • 等等

都可以让这个固定组件失效,就是原本是距离顶部80px固定。

我的组件库没有这个bug,哈哈

mx-design

目前组件不是很多,还在努力迭代中,不知道凭借没有这个bug的小小优点,能不能从你手里取一个star,哈哈

bug原因

affix组件无非都是用了fixed布局,我是如何发现这个bug的呢,我的组件库动画系统用的framer-motion,我本来是想在react-router切换路由的时候整点动画的,动画效果就是给body元素加入例如transform的变化。

然后我再看我的固钉组件怎么失效了。。。后来仔细一想,才发现想起来fixed布局的一个坑就是,大家都以为fixed布局相对的父元素是window窗口,其实是错误的!

真正的规则如下(以下说的包含块就是fixed布局的定位父元素):

  1. 如果 position 属性是 absolute 或 fixed,包含块也可能是由满足以下条件的最近父级元素的内边距区的边缘组成的:

    1. transform 或 perspective 的值不是 none
    2. will-change 的值是 transform 或 perspective
    3. filter 的值不是 none 或 will-change 的值是 filter(只在 Firefox 下生效)。
    4. contain 的值是 paint(例如:contain: paint;
    5. backdrop-filter 的值不是 none(例如:backdrop-filter: blur(10px);

解决方案

  • 首先是找出要固定元素的定位元素(定位元素的判断逻辑上面写了),然后如果定位元素是window,那么跟目前所有组件库的逻辑一样,所以没有bug,如果不是window,就要求出相对定位父元素距离可视窗口顶部的top的值
  • 然后在我们原本要定位的值,比如距离顶部80px的时候固定,此时80px再减去上面说的定位父元素距离可视窗口顶部的top的值,就没有bug了

具体代码如下:

  • offsetParent固定元素的定位上下文,也就是相对定位的父元素
  • fixedTop是我们要触发固定的值,比如距离可视窗口顶部80px就固定
affixDom.style.top = `${isHTMLElement(offsetParent) ? (fixedTop as number) - offsetParent.getBoundingClientRect().top : fixedTop}px`;

本文完毕,求关注,求star!!!对于react组件库感兴趣的小伙伴,欢迎加群一起交流哦!

转载自:https://juejin.cn/post/7265121637497733155
评论
请登录