三年前写的一个代码工具,至今已被 AI Coding 完全取代。

初衷

2022 年在 momenta 实习的时候就经常发现一个代码问题,大家编写的代码中经常出现 style props 和 tailwind css 并存的现象,就像是:

jsx 复制代码
<div className="inline-block" style={{ width: 300 }} />

这个简单的代码已经有了两个问题:

  1. 代码风格不统一。已经引入了 tailwind css,又使用 style props 仅仅作为样式而不是变量
  2. 总是引发重新渲染。style props 使用的字面量 object { width: 300 }, 会在每次父组件重新渲染的时候引发这个组件的重新渲染。如下面这个代码所示:
tsx 复制代码
const CompA = () => {
    const [count, setCount] = useState(0);
    
    return (
        <>
            <div> {count} </div>
            <button onClick={() => setCount(count + 1)}> +1 </button>
            
            <div style={{ width: 300 }}>
                {/* 这里是个巨大的组件 */}
            </div>
        </>
    )
}

编写一个 demo,左边是直接使用 object 字面量编写的 react 组件,右边是经过 useMemo 固化的 object字面量,其在点击按钮加一引发重新渲染后,左侧会跟个重新渲染,而右侧则保持静态不重新渲染。运行效果如图所示

这仅是一个演示 demo,当真正进入生产环境中,被牵连的组件可能规模比较庞大,重新渲染可能导致显示页面跳动、白屏,以及普遍的性能损失和性能优化失败

解决办法

这个问题解决办法的文字描述如下:

首先,行 AST 分析,得到每个组件的抽象语法树数据。

第二,遍历语法树,查询每个 Node 上是否有 style object。

第三,对 Style Object 中的 Properties 进行遍历并通过某些手段映射到 Tailwind CSS string 上。

第四,重构 AST,删除 Style object, 增加 className。

最后,保存文件。


上述步骤中最复杂的是第三步,其需要考虑多种情况:

  • 静态映射
  • 动态映射
  • 状态传递

对于静态映射,其变化为:

tsx 复制代码
{ textAlign: "left" }  -> "text-left"

对于动态映射,其变化为:

tsx 复制代码
{ marginLeft: 1 } or { marginLeft: '1px' } -> "ml-[1px]"

对于状态传递,其应该保留,一般展现形式为变量或者插值:

tsx 复制代码
{ position: 'absolute', top: `${topVar}` } -> "absolute" { top: `${topVar}` }

所以在当时的测试样例中我是这样写的:

js 复制代码
const testSamples = [
    {
        input: `<div style={{ textAlign: 'center' }} />;`,
        output: `className="text-center"`
    },
    {
        input: `<div style={{ textAlign: false }} />;`,
        output: `textAlign: false`
    },
    {
        input: `<div style={{ backgroudUnknow: 'black', textAlign: 'center'  }} />;`,
        output: `className="text-center"`
    },
    {
        input: `<div style={{ padding: '2px' }} />;`,
        output: `className="p-[2px]"`
    },
    {
        input: `<div style={{ padding: 2 }} />;`,
        output: `className="p-[2px]"`
    },
    {
        input: `<div style={{ padding: '2px 4px 2px' }} />;`,
        output: `className="pt-[2px] py-[4px] pb-[2px]"`
    },
    {
        input: `<div style={{ strokeWidth: 4 }} />`,
        output: `className="stroke-width-4"`
    },
    {
        input: `<div style={{ strokeWidth: '4' }} />`,
        output: `className="stroke-width-4"`
    },
    {
        input: `<div style={{ textAlign: 'center !important' }} />`,
        output: `className="!text-center"`
    },
    {
        input: `<div style={{ padding: '100%', margin: 'calc(100%)' }} />`,
        output: `className="p-[100%] m-[calc(100%)]"`
    },
    {
        input: `<div style={{ fontWeight: 500 }} />`,
        output: `className="font-500"`
    },
];

如今

如今,三年后各种 AI coding 工具层出不穷,Claude Code, Gemini Cli, 以及国内的 Qwen Coder,都可以仅用一句提示词做到上述的所有工作:

复制代码
帮我查看一下这个项目,并将所有组件中使用的 React Style Props 切换为 Tailwind css,并输出这样做的好处。

根据你的项目大小,也许 5-15 分钟后,全部的代码已经被改造完成了,并且 AI 的改动可能更具有逻辑性。

并且在你使用 AI 编写的代码中,很少会出现是使用 React Style Props 的情况了。

我的这个小项目也被正式的完全替代了。

相关推荐
大怪v5 小时前
被AI绑架了!
ai编程
腻害兔5 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
不好听6135 小时前
从一行 JSX 到屏幕像素:前端开发者必须懂的浏览器渲染管线
前端
恒拓高科WorkPlus5 小时前
企业级内网即时通讯建设模型:BeeWorks内网IM四层架构
前端
前端小李子6 小时前
前端环境变量裸奔?我用 EnvShield 给它穿了件防弹衣
前端
youtootech6 小时前
HarmonyOS《柚兔学伴》项目实战25-我的页面、Web 嵌入与项目总结
前端·华为·harmonyos
神奇霸王龙7 小时前
GB/T 46886 闭环屠夫:5 旗舰多模态 LLM 工业质检实测
人工智能·计算机视觉·ai·开源·ai编程·本地部署
小林ixn7 小时前
从零到一理解 React 父子组件通信:手写一个 Todo 应用带你彻底搞懂单向数据流
前端·javascript·react.js
三声三视7 小时前
uni-app 鸿蒙端传参变成 [object Object]?顺着源码追到 ArkTS router 底层才搞明白
人工智能·ai·uni-app·aigc·ai编程·harmonyos
醇氧8 小时前
CountDownLatch / CyclicBarrier / Semaphore 面试高频问答清单
前端·面试·职场和发展