- AI 技能
- 人工智能
【免费下载链接】skills
Anthony Fu's curated collection of agent skills.
UnoCSS 的 Attributify 模式允许把工具类拆散成独立的 HTML 属性,但在 React、Preact、Solid 等 JSX 框架中,无值属性(valueless attributify)会被 JSX 编译器改写成={true}形式,从而彻底破坏 UnoCSS 的类名提取。本文围绕transformerAttributifyJsx这一专用 transformer,讲清它解决的问题、工作原理、配置选项(blocklist)、各 JSX 框架下的 Vite 插件接入方式,以及配套的 TypeScript 类型声明,帮助你在 JSX 项目中稳定启用无值 Attributify 写法。
问题背景:JSX 会把无值属性变成={true}
UnoCSS 的 Attributify 预设支持“无值属性”写法(valueless attributify),即把工具类直接作为不取值的属性写在标签上(参见 preset-attributify 参考):
// 你写的是 <div m-2 rounded text-teal-400 />但 JSX 编译器会把没有取值的布尔属性统一改写为显式的true:
// JSX 编译后变成 <div m-2={true} rounded={true} text-teal-400={true} />正是这个={true}导致 UnoCSS 的 Attributify 检测失效——提取器期望的是m-2=""这类空字符串值,而={true}既不是空值、也不符合 Attributify 的取值约定,属性名因此无法被正确识别为工具类。
需要注意的作用边界:UnoCSS 的提取发生在构建时,且默认从 Vite/Webpack 管线中提取.jsx、.tsx、.vue、.md、.html、.svelte、.astro、.marko文件(.js、.ts默认不在提取范围内,详见 core-extracting 参考)。也就是说,JSX/TSX 源文件本来就在扫描对象中,问题只出在“无值属性”这一种写法上。
工作原理:把布尔属性还原回空字符串
transformerAttributifyJsx的作用是把 JSX 编译产生的布尔属性重新转换回空字符串形式,让 UnoCSS 的 Attributify 检测恢复正常:
// 输入(JSX 编译后的形态) <div m-2={true} rounded={true} /> // 输出(transformer 转换后) <div m-2="" rounded="" />转换之后,UnoCSS 就能正常地从这些属性中提取出 Attributify 工具类并生成对应 CSS。从配置角度看,它与transformerDirectives、transformerVariantGroup、transformerCompileClass一样,统一挂在UnoCSS配置的transformers数组中(transformers选项的完整说明见 core-config 参考)。
安装与基本配置
在 UnoCSS 配置中同时启用presetAttributify和transformerAttributifyJsx:
import { defineConfig, presetAttributify, transformerAttributifyJsx } from 'unocss' export default defineConfig({ presets: [ presetAttributify(), ], transformers: [ transformerAttributifyJsx(), ], })UnoCSS 会自动在项目根目录查找uno.config.{js,ts,mjs,mts}或unocss.config.{js,ts,mjs,mts},无需额外指定配置文件路径。
配置选项:blocklist
transformerAttributifyJsx支持通过blocklist排除不希望被转换的属性名:
transformerAttributifyJsx({ // 排除特定属性,不对其进行转换 // 默认:转换所有符合 attributify 模式的属性 blocklist: ['text', 'font'], })默认的转换范围是所有符合 attributify 模式的属性;当某些属性名与 JSX 框架自身的语义冲突、或者你希望保持原样时,把它们加入blocklist即可让 transformer 跳过这些属性。
什么时候必须使用
当你在下列环境中使用无值 attributify 语法时,必须启用该 transformer:
- React
- Preact
- Solid
- 任何基于 JSX 的框架
两种写法的区别在于属性是否带值:
// 这种写法需要 transformer 才能生效 <div flex items-center gap-4 /> // 这种写法带值("~" 表示“前缀自身”,如 flex 即 flex),无需 transformer <div flex="~" items="center" gap="4" />即:带值写法(flex="~"、items="center")本身不经过布尔属性改写,可以正常工作;只有<div flex />这类无值写法才依赖transformerAttributifyJsx做还原。如果项目中统一采用带值写法,也可以不启用该 transformer。
各 JSX 框架下的 Vite 接入
UnoCSS 与 Vite 的集成参考见 integrations-vite 文档,以下是针对 JSX 框架的关键点。
React
UnoCSS()插件必须放在 React 插件之前,这样 UnoCSS 才能在 JSX 转换之前处理源码:
// vite.config.ts import React from '@vitejs/plugin-react' import UnoCSS from 'unocss/vite' export default { plugins: [ UnoCSS(), // 必须位于 React 之前 React(), ], }配套的uno.config.ts:
// uno.config.ts import { defineConfig, presetAttributify, presetWind3, transformerAttributifyJsx } from 'unocss' export default defineConfig({ presets: [ presetWind3(), presetAttributify(), ], transformers: [ transformerAttributifyJsx(), ], })此外,Vite 集成文档中还有一条与 attributify 相关的构建提示:使用@unocss/preset-attributify时,应从 build script 中移除tsc步骤,以避免类型检查因自定义属性报错。
Preact
与 React 相同的插件顺序,使用@preact/preset-vite或@prefresh/vite即可:
// vite.config.ts import Preact from '@preact/preset-vite' import UnoCSS from 'unocss/vite' export default { plugins: [ UnoCSS(), Preact(), ], }Solid
// vite.config.ts import UnoCSS from 'unocss/vite' import solidPlugin from 'vite-plugin-solid' export default { plugins: [ UnoCSS(), solidPlugin(), ], }TypeScript 类型支持
在 JSX 中给 DOM 元素写任意自定义属性,TypeScript 默认会报错。UnoCSS 提供了类型声明方案:presetAttributify包导出了AttributifyAttributes类型,把它混入 React 的HTMLAttributes后,所有 Attributify 属性都能通过类型检查:
// shims.d.ts import type { AttributifyAttributes } from '@unocss/preset-attributify' declare module 'react' { interface HTMLAttributes<T> extends AttributifyAttributes {} }Vue 3 项目的对应写法(混入@vue/runtime-dom/@vue/runtime-core)见 preset-attributify 参考的 TypeScript Support 章节。
配套要点:presetAttributify 的相关选项
启用 valueless 写法时,presetAttributify自身的两个选项与这个 transformer 直接相关(完整选项见 preset-attributify 参考):
presetAttributify({ strict: false, // 仅为 attributify 生成 CSS prefix: 'un-', // 属性前缀 prefixedOnly: false, // 要求所有属性都带前缀 nonValuedAttribute: true, // 支持无值属性(valueless 写法的关键) ignoreAttributes: [], // 忽略的属性 trueToNonValued: false, // 把 value="true" 也视为无值 })nonValuedAttribute: true:声明预设支持<div m-2 rounded />这类无值属性,是 valueless 写法生效的前提。trueToNonValued: false:默认不把value="true"当作无值处理。注意它面向的是字符串"true"取值,而 JSX 产生的={true}是布尔表达式、且发生在源码提取之前的编译阶段,因此不能靠这个选项替代transformerAttributifyJsx——这正是需要 transformer 的根本原因。
另外,当属性名与 HTML 原生属性冲突时,可按 preset 文档的约定使用un-前缀(如<a un-text="red">)规避。
在 skills 仓库中继续深入
本文基于 skills/unocss/references/transformer-attributify-jsx.md 展开,该文档由 UnoCSS 官方文档生成(生成信息见 skills/unocss/GENERATION.md,对应上游源码提交f05ee3a9ed0e1d4490aa7f04fc7aef4bd0babb15,Skill 基于 UnoCSS v66.10.5)。建议结合以下同目录参考一起阅读:
- preset-attributify:Attributify 预设的完整用法、前缀自引用(
~)、冲突属性处理与 TypeScript 声明; - integrations-vite:Vite 插件各模式、各框架插件顺序与 attributify 相关注意事项;
- core-extracting:提取机制、默认文件类型与魔法注释(
@unocss-include等); - core-config:
transformers等完整配置项; - UnoCSS Skill 总览 skills/unocss/SKILL.md:所有 preset 与 transformer 的索引表。
小结
transformerAttributifyJsx专门解决 JSX 编译把无值属性改写为={true}、导致 Attributify 检测失效的问题,原理是把布尔属性还原为空字符串(m-2={true}→m-2="");- 只需在
uno.config.ts中把transformerAttributifyJsx()加入transformers,并与presetAttributify()配合即可; blocklist选项可排除特定属性(如['text', 'font'])不被转换;- 在 Vite 中
UnoCSS()插件必须位于 React/Preact/Solid 插件之前; - 用
@unocss/preset-attributify导出的AttributifyAttributes混入 React 的HTMLAttributes,可获得完整类型支持; - 若团队统一采用带值写法(
flex="~"),则无需启用该 transformer。
- AI 技能
- 人工智能
【免费下载链接】skills
Anthony Fu's curated collection of agent skills.
相关推荐
UnoCSS transformer-attributify-jsx 完整实战指南:在 Airi 仓库的 Vue/JSX 混合场景中启用无值 Attributify
UnoCSS transformer attributify jsx 完整实战指南:在 Airi 仓库的 Vue/JSX 混合场景中启用无值 Attributi
AI 应用人工智能大模型数字人AI Agent语音前端后端桌面应用移动开发即时通讯3D渲染在UniApp X项目中正确使用UnoCSS的解决方案
在UniApp X项目中正确使用UnoCSS的解决方案 UniApp X作为新一代跨平台开发框架,结合UnoCSS这一原子化CSS引擎,能够显著提升开发效率。然
前端构建工具在 ice.js 中使用 @ice/plugin-jsx-plus:为 React 应用接入 JSX+ 声明式语法
在 ice.js 中使用 @ice/plugin jsx plus:为 React 应用接入 JSX+ 声明式语法 本文基于当前仓库 packages/plug
前端Web框架SSR前端构建插件系统微前端跨平台
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考