如果我放弃 React,那一定只有一个原因

React中使用class替代className的方法

我研究了一下,看看能不能直接在 React 组件中直接使用 class,而不是 ​​className​​,这样我的代码演示不就对味儿了吗?这一次,折腾了一会儿,我还真研究出来了!

React 有一个我忍了很久的痛点。如果有一天,我决定放弃 React 转向其他的框架,那么一定是这个痛点我终于忍不了了。

这个痛点就是 className

<div className='relative pt-16'></div>

    特别是最近我正在写一本关于 CSS 的专栏时,这个痛点已经把我逼到了几乎忍受不了的程度。

    由于我的网站里,为了确保一致性、真实性、有效性,文章里的案例全部都是直接使用的内嵌案例的真实代码,但是网站是用 React 来写的,因此能够直接运行的代码也是 React 组件,展示出来的也就是 React 的代码。

    但是这本专栏是专门介绍 CSS 的,如果代码中展示出来的是使用的 className,反正我不知道其他人是什么感受,我是越看越别扭,总感觉哪哪哪都不对劲。

    所以我就想要研究一下,看看能不能直接在 React 组件中直接使用 class,而不是 className,这样我的代码演示不就对味儿了吗?

    这一次,折腾了一会儿,我还真研究出来了!复制

    export default function Page() {
      return (
        <div class='relative pt-16'>
          <div class="fixed inset-0 -z-10">
            <div class="absolute inset-0 bg-[linear-gradient(to_right,#80808012_1px,transparent_1px),linear-gradient(to_bottom,#80808012_1px,transparent_1px)] bg-[size:40px_40px]"></div>
          </div>
          ...
        </div>
      )
    }

    我们先来了解一下 className 的历史原因,以及使用 class 之后可能会存在的问题,最后再给大家介绍具体如何操作。

    1.历史原因

    className 在 React 社区中争议了很多年,但是在设计之初,据说是为了在 token 层面,与声明类的关键字 class 区分开来,因此选择了重命名为 className

    class MyComponent extends Component {
      // ...
    }

    不过除此之外,dan 在 github 中有提过另外一个理由。如下所示,在 JavaScript 中,给 DOM 设置属性有两种方式,一种是 property,另外一种 attribute

    node.value = 10; // setting a property
    node.setAttribute('value', '10'); // setting an attribute

    而 JSX 由于被约定为是 JS 语法的扩展,因此,React 团队认为使用 JS 默认的 className 字段给 DOM 设置属性比较合适。

    node.className = ''  // 表现为 property,而非 attribute

    2.争议

    尽管 dan 为此解释了很多次,但许多 React 开发者并不为此买账,在社区中强烈要求能够在 JSX 中使用 class

    并且在后续的更新中,提议将 className 修改为 class 的声音越来越大。

    React 团队为此不得不做出了妥协。

    因此,在 React 17/18 的版本中,其实我们就可以直接在 JSX 中使用 class 了。但是他们又没完全妥协,选择的方式是,你可以用,代码也能正常运行,但是 React 会给你报错 ~ 就很恶心

    dan 的解释是,

    如果 React 团队毫无预警的同时支持 class 与 className,会在 React 生态中造成巨大的分歧。并不是所有的三方库都会同时兼容这两个方案,如果你使用的某一个三方库不兼容 class,那么就会导致样式的传递中断,出现问题。

    React 团队无法完全左右社区,对于这种冲突无能为力,因此,长期以来,class 仍然以预警的方式存在。

    但是,忍了 7 年了,我已经忍不了了,我决定不管要付出什么样的代价,必须要用 class,哪怕最后放弃使用 react。

    那为了使用 class,我们要做什么额外的事儿呢?

    3.弊端以及如何解决

    在这之前,我们要明确,React 中,是支持直接使用 class 的。因此从功能的角度上而言,我们啥也不需要做,直接用就可以了。

    但是当你直接使用之后,你会遇到一堆麻烦事儿需要解决。

    首先,如果你的项目中使用了 TypeScript,他会疯狂报错,为了解决这个问题,我们要去修改 TypeScript 的类型声明。

    在 @types/react 这个库中,我们在 HTMLAttributes 这个类型下面新增 class 字段。

    interface HTMLAttributes<T> extends AriaAttributes, DOMAttributes<T> {
      ...
      className?: string | undefined;
      class?: string | undefined;
      ...
    }

    处理好之后就搞定了。不过手动修改有一个比较麻烦的地方,就是每次你重新 install 之后,这段代码就会被覆盖,又还原成之前的样子。那么这个时候你有两个选择,

    第一,由于修改起来比较简单,而且 install 频率也非常低,因此你可以每次都手动修改一下。

    第二,你在 install 时执行一个本地脚本,用 node 代码自动去插入这段逻辑。

    接下来的一个问题就是 eslint 等语法检测规则可能会报错,我们可以修改 ESLint 配置文件以消除这个错误。

    "react/no-unknown-property": ["off"]

    然后就是在开发环境中,console 面板里会报错,如下所示:

    为了解决这个问题,我们需要在项目入口处,重写 console.error 的报错规则,具体代码我也已经研究出来了,分享给大家。

    const originalError = console.error;
    
    console.error = function(...args) {
      const ignorePatterns = [
        'Invalid DOM property `%s`. Did you mean `%s`?',
        'class',
        'className'
      ];
    
      let shouldIgnore = true;
    
      ignorePatterns.forEach((pattern, index) => {
        if (typeof args[index] !== 'string' || !args[index].includes(pattern)) {
          shouldIgnore = false;
        }
      });
    
      if (!shouldIgnore) {
        originalError.apply(console, args);
      }
    };

    这段代码仅会消除 class 的报错,而不影响其他。

    到这里,基本上所有的报错都解决掉了。

    当我在群里和朋友圈分享这个的时候,有朋友问我是不是引入了什么三方工具或者插件,或者会不会影响编译结果,现在大家知道了,我没有用任何三方工具,只是修改了一些无关痛痒的报错提示。

    并且,对于代码执行、编译不会有任何影响。

    最后一个问题,如果你正在开发底层组件库,并且决定支持 className 的传入时,这里还会遇到一个新的问题。一个就是你需要同时支持 class 的传入,并且,当你使用结构时,必须对 class 进行重命名

    const { class: cls } = props;

      这个小的细节是 React 团队所担心的,会引起社区分歧的核心原因。但是如果是个人项目,你可以完全把控你的代码细节,那么这个分歧对于个人来说并不会有太大的影响。

      4.总结

      这是一个个人偏好的操作,我并不推荐大家像我一样使用。如果你也跟我一样讨厌 className,并且决定在项目中使用 class,可以参考一下我的做法,我基本上把潜在的隐患都考虑到了,放心使用是没问题的。

      AI大模型学习福利

      作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

      一、全套AGI大模型学习路线

      AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

      因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取

      二、640套AI大模型报告合集

      这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

      因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获

      三、AI大模型经典PDF籍

      随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。


      因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获

      四、AI大模型商业化落地方案

      因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获

      作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量

      评论
      添加红包

      请填写红包祝福语或标题

      红包个数最小为10个

      红包金额最低5元

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

      抵扣说明:

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

      余额充值