开发者社区 > 博文 > 开启一码五端,NutUI 组件库助力黄流跨端实现
分享
  • 打开微信扫码分享

  • 点击前往QQ分享

  • 点击前往微博分享

  • 点击复制链接

开启一码五端,NutUI 组件库助力黄流跨端实现

  • hanyuxinting
  • 2026-02-12
  • IP归属:北京
  • 25浏览

    在最近结束的“京东订单鸿蒙-回跨iOS/安卓”的项目中,NutUI 作为京东移动端的开源组件库,再次承担起一环重要的工作,为布局搭建、设计交互、无障碍、多语言、多模式实现等,提供了完备的基础能力,并出色的完成了三端的工作,基本实现了基于 Taro 框架的一码五端能力,开启了业内组件库跨端能力的新篇章。

    基于业务与基建能力的重组

    背景

    在2024年到2025年,NutUI 基于鸿蒙和 iOS/安卓做了基本的适配工作,不过整体项目是实验中状态,最早在2024年发布了 DongDesign UI 的一码多端版本,并开放了鸿蒙支持的能力,整合了 Taro Components 及 NutUI 组件库,期望给开发者提供在 Taro 跨端中引用一套组件的便捷方式。

    这是一个好的开端,让 Taro Components 和 NutUI 作为整合整体出现,这为在黄流跨端实现中提供了更直接的技术支持,并及时响应黄流业务侧提出的核心诉求——希望可以通过引用一个组件库,让整个项目在使用组件库的能力上更统一、规范、无痛。

    很快,这件事达成了一致,并推动了第一版 黄流业务的基础组件库 落地——@hlfe/ui 的第一个版本的出现。@hlfe/ui 主要是为了赋能黄流业务侧,覆盖黄流订单、商详、购物车、结算,在优先考虑适配鸿蒙、iOS和安卓的前提下,初步整合了 Taro Components 公共组件及 NutUI 的 30+ 组件。组件的数量及能力,会继续随着业务侧的需求及基建适配能力陆续开放。


    组件库间的关系

    考虑到这一年多的时间内,突然出现了许多组件库的名字,这里首先对它们的关系做个厘清。



    首先,我们可以简单粗暴的把它们的关系理解为上图的包含关系。Taro 作为框架,jdtaro/ui 是 Taro 提供的对外的基础组件,包含容器类、Form表单等基础能力,可看做是原来的 @tarojs/components 在 jd 域内的别名(目前这两个都可以引用,可关注 Taro 官网)。

    第二,NutUI 在跨端能力是基于 Taro 框架来实现的, @jdtaro/ui (@tarojs/components) 是整个 NutUI 组件库的实现跨端的基座。

    第三,@hlfe/ui 是面向黄流的开发者,包含前端、原生同学,为了让大家用起来省事、统一,将 NutUI 和 Taro 基础组件整合在一起,为大家提供了一个统一的引用入口。

    未来,在其他业务场景里,如果实现一码五端,大家可以使用 hlfe/ui 来统一处理;也可以继续保留原引用逻辑。


    hlfe/ui 的实现

    hlfe/ui 的核心诉求是希望在项目中引用组件库的方式统一、集中,不用引多个 UI 组件库。所以,在实现中,也是以核心诉求为准,将项目中涉及的组件库收口处理。

    双层组件架构

    基于 Taro 的跨端项目中,项目依赖的组件主要来源于 Taro 基础组件库 jdtaro/ui 及基于主站实现的高阶组件库 NutUI,需要整合这两个组件库。在整合中,我们主要关注以下能力,以更好的服务业务。

    1、基础组件与通用组件的整合

    容器组件与通用组件的割裂,是导入两个组件库的根本原因。所以,在组件结构上,直接将两者可用组件导出。

    组件库
    组件列表
    基础容器组件
    @jdtaro/ui
    View、ScrollView、Text、List
    通用 UI 组件
    @nutui/nutui-react-taro
    Button、Dialog、Toast、PopUp、Divider、Tabs、CheckBox、Radio、Switch、Empty、Input、TextArea、Price、CountDown、CalendarCard等

    2、性能优先

    在跨端的交付中,希望在满足交互复杂性的同时,会关注性能最优导出的策略。比如 Image ,我们优先会导出 jdtaro/ui 原组件,确保在各个端上都有实现此类组件的前提下,保障此类组件的性能最优;也会保留 NutUI 组件,并以 NutImage 导,以在基于端的性能优化下,保障组件功能的丰富性。

    3、更多共用能力

    1)类型定义:在跨端项目中,基本都使用了 TS,为了更兼容此类支持,在 hlfe/ui 中导出了组件定义相关的类型。

    2)公共方法,在组件库中沉淀的一些高效公共方法,也一并为开发者提供,便于大家快速交付。

    3)主题定义,Design Token 在组件库中的应用,方便大家可以快速的切换主题,包括正在支持的 京东到家、京犀 等主题;并直接为开发者提供相应的暗黑定义。

    智能导出组件

    通过构建脚本,完成了对组件最新能力的拉取、合并及导出。

    // 导出 jdtaro/ui
    indexContent.push(
        `import { ${com.name} as T${com.name} } from '@jdtaro/ui'
         const ${com.name} = T${com.name}
         export {${com.name}}
        `
    )
    
    // 导出 NutUI 公共组件
    indexContent.push(`export { default as  ${com.name} } from '@nutui/nutui-react-taro/dist/es/packages/${com.name.toLowerCase()}'`)
    
    // 导出公共方法等
    indexContent.push(`export * from '@nutui/nutui-react-taro/dist/es/utils'`)
    indexContent.push(`export * from '@nutui/nutui-react-taro/dist/es/hooks'`)
    


    hlfe/ui 的使用

    创建项目

    使用 jd-init搭建项目后,可选用 NutUI-React 模板,在完成项目后,进入项目配置。

    taro jd-init my-taro-project
    

    这时,需要关注几点:

    确认包引入

    1、在 package.json 中,确保已包含以下内容:

    "@hlfe/ui": "0.0.3-cpp.ios.18-beta.10",
    "@jdtaro/ui": "4.0.3-beta.34",
    "@nutui/icons-react-taro": "3.0.2-cpp.3.beta.4",
    "@nutui/nutui-react-taro": "3.0.19-cpp.23",
    

    确认配置项

    2、回跨到 iOS/安卓 项目时,需要关注 config/index.ts 中的配置,避免编译时异常:

    esnextModules: [
        'jdtaro',
        '@hlfe/ui',
        '@nutui/nutui-react-taro',
        '@nutui/icons-react-taro',
    ],
    

    组件使用

    3、组件使用

    import { Popup } from '@hlfe/ui'
    return (
        <Popup
          visible={visible}
          title={title}
          position={position || `${isBigScreen ? 'right' : 'bottom'}`} // 大屏处理
          closeable={parameter?.closeable ?? true}
          {...rest} // 透传原组件属性
          style={{ height, ...parameter.style, ...bigScreenRect, maxHeight: '100%' }}
          closeAriaLabel={intl.formatMessage({ id: 'xxx_id' }) || '关闭'} // 无障碍读取配置
          onClose={() => {
            closePop()
            parameter?.onClose?.(parameter?.outProps)
          }}>
          {content}
        </Popup>
    )
    


    文档与反馈

    文档https://nutui.jd.com/taro/react/3x/#/zh-CN/component/buttonhttps://npm.m.jd.com/package/@hlfe/ui
    咚咚群1025679314
    提交issuehttps://github.com/jdf2e/nutui-react/issues


    核心能力的优化

    hlfe/ui 的核心能力,是落在 Taro 的基础组件与 NutUI 的跨端适配上,本篇主要关注 NutUI 的跨端适配及能力建设。

    在鸿蒙和回跨到 iOS/安卓项目中,最大的问题在于曾经在 web 和小程序端表现良好的布局与样式,会以各种奇怪的方式呈现,比如从中间弹出的弹框,会从右下方弹出;比如 Tabs 切换时,TabPane 成了白屏;比如主站不支持 SVG,Checkbox 就无法展示。这样的问题在项目中层出不穷,就需要一个一个的修改,并push上下游建设。

    五端适配

    区别于黄流业务的鸿蒙、iOS、安卓适配,作为基建,需要更多的关注在兼容已有能力的基础上实现新的适配

    Taro 基建为无法支持的属性与API 提供了工具,可以快速的识别到当前项目中,在 iOS 与 安卓上无法识别的能力。在运行以下命令后,需要特别关注 errors 信息,这些会阻塞业务项目的编译。

    pnpm run build:dynamic --disable-upgrade --pages=pages/index/index --atom-collection --generate-source
    


    在解决这些无法支持的属性与API时,主要考虑几点:

    1)基础适配,如将原来的 divspan 等 web 端标签改为 Taro 标签。

    2)兼容五端,通过判断端来做不同的处理。

    /* #ifdef harmony dynamic*/
    width: 80px;
    /* #endif */
    /* #ifndef harmony dynamic*/
    width: auto;
    /* #endif */
    

    3)改进实现,规避不支持的属性或API。

    // 不建议
    left: -var(--nut-spacing);
    align-items: start;
    
    // 建议:
    left: calc(-1 * var(--nut-spacing));
    align-items: flex-start;
    

    4)废弃 API 移除,如 getAppBaseInfo等。


    能力扩充

    在交付黄流的项目中,会对组件库提出更精确的需求,为此,对部分组件进行了功能扩充。

    1)Popup 组件:支持拖拽变更半弹层的高度、支持 top 属性可供展示营销位等;

    2)SearchBar 组件:增加 inputProps 属性,暴露更多的 input props 内置属性;

    3)Input 组件:增加 style 属性透传至 native Input 组件;

    4)Dialog 组件:底部按钮增加角标;

    5)CountDown 组件:支持千分位展示;

    6)Avatar 组件:支持图片填充模式;

    7)NoticeBar 组件:优化宽度获取逻辑。


    无障碍支持

    为了更好的回跨,APP侧也对无障碍输出了统一的规范,基于整体规范,NutUI 也对无障碍进行了完善。

    1)统一规范

    属性名
    类型
    说明
    ariaRolestring角色
    ariaLabelstring为元素提供一个可访问名称,通常用于没有可见文本说明的控件。
    ariaHiddenboolean指定元素是否对辅助技术隐藏。true表示隐藏,false表示可访问。
    ariaCheckedboolean用于复选框、开关等控件,标识当前是否被选中。
    ariaSelectedboolean指示元素是否处于选中状态,常用于选项卡、列表项等。
    ariaRoledescriptionstring为元素的role提供额外说明,帮助辅助技术进一步解释该元素的功能。

    2)读取顺序

    ariaLabel→value→ariaRole→hint的顺序组合朗读。

    3)当前实现

    在大部分的组件中,View 和 Text 读取是正常的,新增了如有交互行为的组件的无障碍属性,如 CheckBox、Radio等,支持 ariaLabel 的自定义。

    4)已知问题及待解决

    在无障碍的实现中,iOS/安卓的表现相对来说较好。鸿蒙端,如弹出弹层时,无法自动获取焦点,需要手动触发可读取内容。类似问题会影响 Dialog、Toast、Popup 等弹层。


    Icon 库升级

    Icon 是组件中不可获取的部分,在实现鸿蒙/iOS/安卓的适配中,采用了 Image src 引入 svg 链接的方式。

    import React from "react";
    import "@tarojs/components";
    const IconSVG = (props) => {
      const realProps = { ...defaultProps, ...props };
      return React.createElement(Icon2, { ...realProps, name: realProps.name || "Add", svgSrc: "https://storage.360buyimg.com/imgtools/81adb71e35-159c76f0-a824-11f0-8300-eb1b11b7ce6f.svg" }));
    };
    

    在实现中,难点在于推动主站 SVG 的基建,比如 无法展示 SVG,SVG 无法变更颜色,SVG 对于导出图片大小有要求。可喜的是,主站基建 SVG 的能力,目前正在向真实的 SVG 落地,对于图片库导出方来说,成本会显著降低。


    同时,Icon 库也补齐了无障碍的能力,这样方便了开发者在使用 icon 时,可以做读取屏蔽或读取设置,大大方便了在项目中处理无障碍的设置。

    比如在 CheckBox 组件中,对于 Icon 需要禁用可读。设置如下:

    <Checked className={color()} ariaHidden />
    

    而在组件维度,可以这样设置,保障组件的无障碍的支持:

    <View
          className={classNames(
            classPrefix,
            className
          )}
          {...rest}
          onClick={handleClick}
          ariaRole="checkbox"
          ariaLabel={ariaLabel}
          ariaChecked={innerIndeterminate ? 'mixed' : innerChecked}
        >
          <Checked className={color()} ariaHidden />
        </View>
    

    在项目内,可以这样设置:

    <Checkbox
        className={styles.checkbox}
        checked={shipShopData?.venderShipmentVO?.selected}
        ariaLabel='读取文案' // 或读取文案
        // ariaHidden={true} // 或禁用掉
    />
    

    回顾与总结

    如今,@hlfe/ui 已开放了 30+ 组件,持续支持了 订单鸿蒙、订单iOS/安卓回跨、商详鸿蒙、结算鸿蒙、购物车鸿蒙;当前还在对商详、结算和购物车的回跨交付中,未来会对更多组件进行开放。

    回顾这段时间,是与业务侧、Taro侧、基建能力紧密协作的一段历程。对于组件库与业务来说,都是一个快速迭代过程,其中也遇到了一些痛点,为此,我们希望可以在“提交issue-评审-提交PR-发布版本”的共建模式下,加快整个流程的执行落地,以快速响应业务侧的诉求,并给开发者提供更多共建的可能性。

    邀请共建

    欢迎更多的伙伴们,加入我们,一起共建,在一码五端的世界里遨游~

    咚咚号:1025679314

    Github: https://github.com/jdf2e/nutui-react

    更多文章

    升级你的前端开发体验: JoyCoder-VSCode现支持 NutUI工作区

    NutUI 单元测试:从 jest 到 vitest

    NUTUI-React 弹幕组件的实现

    NutUI-React 如何实现 RTL

    2023倒带:年度工作汇报


    特别鸣谢

    感谢端技术、质量团队等团队的各位老板在过程中给予的充分指导,让整个项目始终按照正确的航向前行;

    感谢整个项目组业务与基础建设相关项目产研测同学的密切合作,互相的充分信任是项目大胆向前的有力保障;

    感谢各位上下游同学、平台同学、版本同学的鼎力支持,顺利解决了上下游依赖、高可用诉求、灰度验证等关键难题。

    订单一码多端系列文章

    •方案选型与总体设计:主站黄流的3倍效率革命试点:京东App订单一码多端整体回顾

    •业务重构经验篇:订单模块Taro一码三端业务改造经验分享:从多端困境到动态化转型之路

    •工程架构篇:京东黄流"一码三端"重构:规模化协作下的工程架构实践

    •Taro SDK开发能力与效率篇:Taro 5.0:跨端架构演进与业务规模化落地实践

    •性能优化篇:黄流订单列表性能优化实践:一码三端下的业务层性能攻坚之路

    •公共组件篇:开启一码五端,NutUI 组件库助力黄流跨端实现

    •CI/CD篇:黄流订单列表页CI/CD实践:一码三端项目业务层提效之路

    •高可用篇:黄流订单一码多端高可用建设拆解:高速上换发动机的安全保障

    •AI提效篇:Cursor + GPT‑5‑Codex:从“匆匆忙忙”到“从从容容”的跨端提效与质量保障实践




    文章数
    1
    阅读量
    25

    作者其他文章