ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

@expo/html-elements 演进史:从 CHANGELOG 看 Expo 通用语义化 HTML 组件的跨端实现

@expo/html-elements 演进史:从 CHANGELOG 看 Expo 通用语义化 HTML 组件的跨端实现 expo/html-elements 演进史从 CHANGELOG 看 Expo 通用语义化 HTML 组件的跨端实现【免费下载链接】expoAn open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.项目地址: https://gitcode.com/GitHub_Trending/ex/expoexpo/html-elements 是 Expo 官方仓库中一个「小而精」的通用 UI 包它把div、h1、table、header等语义化 HTML 元素封装成 React 组件让同一份代码在 iOS、Android、Web 与桌面端渲染出「各自平台最正确」的原生节点。本篇文章以该包的 CHANGELOG.md 为骨架逐版本解读其关键变更并对照 源码 与 README 验证每一项改动背后的实现细节帮助你在实际项目中选择版本、理解样式过滤与 Babel 转换机制并正确使用这套组件体系。一、包定位为什么需要语义化 HTML 组件Expo 官方建议优先使用View、Image、Text这类平台无关的原语但 Web 上原生存在、移动端却没有直接对应的结构如table、footer、nav很难只用这些原语表达。expo/html-elements的目的正是补齐这一空白——按 README 的描述它是 Simple, light-weight, and well tested, universal semantic HTML elements同时保持对 iOS 与 Android 的最优适配SEO 与无障碍Web 端渲染出真实的 HTML5 标签如h1、header让爬虫索引更准确原生端则映射到平台语义例如H1在 Web 上是h1 /在 iOS 上是UILabel语义在 Android 上是TextView语义类型安全TypeScript 覆盖 iOS / Android / Web不再需要给Text打补丁来使用href零副作用在 package.json 中显式声明sideEffects: false天然支持 tree-shaking。当前包的版本为57.0.0见 package.json与 CHANGELOG.md 顶部 57.0.0 - 2026-06-25 对应。二、安装与快速上手yarn add expo/html-elements导入即可使用import { H1, P, A, Table, THead, TH, TBody, TR, TD } from expo/html-elements; export default () ( H1Hello Expo/H1 P一段语义化段落/P A hrefhttps://expo.dev target_blank链接/A / );所有组件都接受StyleSheetAPI 生成的样式这与react-native的用法完全一致。组件的统一出口在 src/Elements.tsx它把 Headings、Anchor、Layout、Text、Rules、Table、Lists 七大类组件全部导出。三、组件全景HTML 元素到跨端组件的映射README 中给出了一张完整映射表支持的元素均为对应语义 HTML 的「首字母大写」形式HTMLexpo/html-elementsHTMLexpo/html-elementsa /A /main /Main /article /Article /mark /Mark /aside /Aside /nav /Nav /b /B /p /P /blockquote /BlockQuote /pre /Pre /br /BR /q /Q /caption /Caption /s /S /code /Code /section /Section /del /Del /span /Span /div /Div /strong /Strong /em /EM /table /Table /footer /Footer /tbody /TBody /h1 /~h6 /H1 /~H6 /td /TD /header /Header /tfoot /TFoot /hr /HR /th /TH /i /I /thead /THead /li /LI /time /Time /ul /UL /tr /TR /尚未实现Pending的有details /、summary /、progress /、select /、picture /、figure /、figcaption /、form /、label /。而对于audio、button、input、canvas、iframe、img、video、backdrop-filter、linear-gradient等能力官方建议直接使用 Expo 生态中的通用模块如expo-av、expo-image-picker、expo-gl、expo-blur、expo-linear-gradient或 react-native 内置组件而不是在本包中重复造轮子。四、以 CHANGELOG 为线索版本演进与源码印证CHANGELOG 中多数版本标注为 no user-facing changes纯内部迭代但少数关键版本携带了实质性的功能与修复下面逐条对照源码展开。4.1 Unpublished适配 React Native 0.87 的原生 backgroundImage当前待发布版本Unpublished只有一个 Bug fixSupport React Native 0.87s nativebackgroundImagestylewiden the style type to accept gradient arrays in addition to CSS strings, and stop stripping the property from styles on native. (#47729)对照 src/primitives/View.tsx 可以看到类型层已放宽为联合类型backgroundImage?: NativeViewStyle[backgroundImage] | string;即既接受 React Native 原生样式类型RN 0.87 开始原生支持backgroundImage可传渐变数组也接受 Web 的 CSS 字符串写法。同时在 src/css/filterStyles.ts 的WEB_STYLES黑名单中并不包含backgroundImage意味着该属性在原生端会被放行而非剥离——这正是 changelog 所述 stop stripping the property 的实现证据。反观backgroundPosition、backgroundSize、backgroundRepeat等仍属 Web 专属样式会被过滤掉。4.2 0.13.0等宽字体与依赖声明规范化0.13.0 包含两项实质变更Use modern monospace font for web and iOS#37789影响Code /与Pre /两个等宽字体组件。README 中记录了其历史行为——iOS 与 Web 用Courier、Android 用monospace0.13.0 将 Web 与 iOS 的默认等宽字体更新为更现代的字族。Add missing peer dependencies onreactandreact-nativeand optional peer dependency onreact-native-web#38570在 package.json 中可以看到peerDependencies为react: *、react-native: *、react-native-web: *且react-native-web被标记为optional: true——纯原生项目可以不安装它。4.3 0.12.3升级 React 19 并移除编译产物0.12.3 的 Breaking change 是Upgrade to React 19 and remove compiled build code. (#36273)从 package.json 的types/react: ~19.2.2可以印证 React 19 版本线。而 remove compiled build code 则对应其exports字段中提供的expo-source条件导出exports: { .: { types: { expo-source: ./src/Elements.tsx, default: ./build/Elements.d.ts }, expo-source: ./src/Elements.tsx, default: ./build/Elements.js } }在 Expo 的编译链路中会优先解析./src/Elements.tsx源码./primitives/*子路径也提供了同样的源码优先机制。同版本还把 Web 测试切换到了testing-library/react对应 devDependencies 中的testing-library/react: ^16.3.0与testing-library/dom。4.4 0.11.2outlineColor 类型修正以兼容 RN 0.77change type ofoutlineColortoColorValueto support react-native 0.77 (#33946)在 src/primitives/View.tsx 中可以看到outlineColor?: ColorValue正是此改动的落地结果。outlineColor属于 Web 专属样式outline也在WEB_STYLES黑名单中但在类型层使用ColorValue让它在 RN 0.77 的原生侧具备正确类型。4.5 0.9.0 与 0.11.0React Native 版本兼容声明0.9.0Added support for React Native 0.73.0#24971、#254530.11.0Added support for React Native 0.76.x#31552。这类版本以 Notice 形式发布表明该包始终跟随 react-native 主版本线做适配验证升级 RN 版本时应关注对应版本的expo/html-elements。4.6 0.8.0 与 0.7.0向新版 react-native-web 与源码分发演进0.8.0Migrate to use non-deprecatedreact-native-webprops#24930避免使用 react-native-web 已废弃的旧 prop0.7.0Ship untranspiled JSX to support custom handling ofjsxandcreateElement#24889——源码直接分发让下游可以自定义 JSX 转换行为。4.7 0.4.x样式安全过滤与 Babel 保护核心机制成型0.4.1 与 0.4.3 确立了本包最重要的两个底层机制0.4.1 — Strip unsupported web styles on native#21069原生端会剥离WEB_STYLES黑名单中的 Web 专属样式boxShadow、filter、grid*、transition*、animation*、cursor、userSelect、backdropFilter等见 src/css/filterStyles.ts避免把不支持的属性传给原生组件导致崩溃。过滤之外还会做原生侧修正if (style.visibility) { if (style.visibility hidden) style.opacity 0; delete style.visibility; } if (style.position ![absolute, relative].includes(style.position)) { console.warn(Unsupported position: ${style.position}); style.position relative; }filterStyles由 src/css/createSafeStyledView.native.tsx 包装成createSafeStyledView对传入的style做useMemo缓存过滤View原语即由它包一层见 src/primitives/View.tsx。0.4.1 — Better assertions for text children in View components in development-mode#21069生产环境则直接使用原生View零运行时开销。0.4.3 — Babel 插件加固#21594 目录及其测试 babel/tests/transform.test.js。五、跨端样式适配rem/em 单位与 Yoga 布局标题组件在 Web 上使用原生 CSS 单位在原生端换算成像素。核心实现在 src/css/units.tsexport function rem(value: number): number | string { if (Platform.OS web) return ${value}rem; return PixelRatio.getFontScale() * 16 * value; } export function em(value: number): number | string { if (Platform.OS web) return ${value}em; return rem(value); }即 Web 端保留rem/em语义跟随根字号与父字号原生端按fontScale × 16换算为逻辑像素。以 src/elements/Headings.tsx 为例H1使用fontSize: em(2)、marginVertical: em(0.67)、fontWeight: bold完整复刻了 WebKit 的html.css默认标题样式六个标题组件由createHeadingComponent(level)工厂统一生成Web 端注入aria-level与role: header原生端注入accessibilityRole: header。布局类组件Header、Main、Footer、Section、Nav等继承View的共享样式以适配 Yoga 布局引擎display恒为flexYoga 只实现了 flexflex-direction恒为column而非 Web 默认的row。各布局组件的 ARIA 角色在 src/elements/Layout.tsx 中定义例如HeaderWeb 渲染header rolebanner /iOS 使用UIAccessibilityTraitHeaderAndroid 使用CollectionItemInfoCompatNav→role: navigationMain→role: mainArticle→role: articleAside→role: complementaryFooter→role: contentinfoSection统一为role: summary源码注释中标注了 region? 的取舍。A /的实现在 src/elements/Anchor.tsxWeb 端把target/download/rel放进hrefAttrs原生端在onPress中调用Linking.openURL(href)打开链接rolelink保证无障碍语义。BR /在原生端渲染为{ height: 8, width: 0 }的占位 View表格组件则约定原生端只有TH/TD能放文本colSpan/rowSpan目前仅 Web 生效。六、Babel 插件把 react-dom 元素转换成 html-elements如果不想显式引入组件可以在babel.config.js中启用内置插件// babel.config.js module.exports { plugins: [expo/html-elements/babel], };输入export default function Page() { return ( div h1Hello World/h1 /div ); }输出自动补 importprops 原样透传import { Div, H1 } from expo/html-elements; export default function Page() { return ( Div H1Hello World/H1 /Div ); }该插件的转换行为有完整的快照测试保障见 babel/tests/transform.test.js 与 babel/tests/snapshots/transform.test.js.snap。七、测试与质量保障包内对每个元素族都有跨平台快照测试覆盖 Android / iOS / Web 三个平台例如src/elements/tests/Layout.test.web.tsx、Layout.test.ios.tsxsrc/elements/tests/Table.test.web.tsx、Table.test.ios.tsxsrc/elements/tests/Anchor.test.ios.tsx、Anchor.test.web.tsx样式过滤的专项测试 src/css/tests/createSafeStyledView.test.native.tsx以及开发态断言测试 src/primitives/tests/createDevView.test.tsx。package.json 中的 jest 配置采用三个 project 分别以jest-expo/web、jest-expo/ios、jest-expo/android预设运行快照产物*.snap.web、*.snap.ios、*.snap.android逐一验证了各平台的渲染结果。八、版本节奏速览与选型建议版本时间关键内容Unpublished—支持 RN 0.87 原生backgroundImage渐变数组 CSS 字符串原生不再剥离该属性57.0.02026-06-25无用户可见变更56.0.1 / 56.0.02026-05无用户可见变更55.0.2 ~ 55.0.02026-01 ~ 2026-0255.0.0 修复 Windows 下 check-packages 报错0.13.02025-08-13Web/iOS 现代等宽字体补齐 peerDependencies0.12.32025-04-22升级 React 19移除编译产物、源码优先分发0.11.22025-01-19outlineColor类型改为ColorValue兼容 RN 0.770.11.02024-10-22支持 RN 0.76.x0.9.02023-12-12支持 RN 0.73.00.8.02023-11-14迁移到非废弃的 react-native-web props0.7.02023-10-17发布未转译 JSX0.4.32023-05-08Babel 插件不跑 node_modules不转译html/body0.4.12023-02-09原生剥离 Web 样式开发态文本子节点断言选型建议如果你的项目使用 React 19 RN 0.77且需要最新的原生backgroundImage能力建议直接使用当前主线版本57.x如果锁定旧 RN 版本则按上表对照选择 0.9.0RN 0.73、0.11.0RN 0.76等兼容版本。所有关键机制的源码都集中在 packages/html-elements/src 的css/、elements/、primitives/三个目录中阅读顺序推荐Elements.tsx→elements/各文件 →css/filterStyles.ts→primitives/View.tsx即可完整掌握该包的设计全貌。【免费下载链接】expoAn open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.项目地址: https://gitcode.com/GitHub_Trending/ex/expo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表