NutUI组件库基于Taro框架的跨端实践与优化

Viewed 0

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

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

背景

2024年至2025年,NutUI基于鸿蒙和iOS/安卓进行了基本适配工作,整体项目处于实验状态。最早在2024年发布了DongDesign UI的一码多端版本,开放了鸿蒙支持能力,整合了Taro Components及NutUI组件库,旨在为开发者在Taro跨端中提供引用一套组件的便捷方式。这为黄流跨端实现提供了更直接的技术支持,并响应了业务侧核心诉求——通过引用一个组件库使项目在使用组件库时更统一、规范、无痛。随后,推动了第一版黄流业务基础组件库@hlfe/ui的落地,主要赋能黄流业务侧,覆盖订单、商详、购物车、结算等场景,在优先适配鸿蒙、iOS和安卓的前提下,初步整合了Taro Components公共组件及NutUI的30+组件,组件数量及能力将随业务需求及基建适配陆续开放。

组件库间的关系

为厘清组件库间的关系,可以简单理解为包含关系:Taro作为框架,jdtaro/ui是Taro提供的对外基础组件,包含容器类、Form表单等基础能力,可视为@tarojs/components在京东域内的别名。NutUI的跨端能力基于Taro框架实现,@jdtaro/ui是整个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、更多共用能力
包括类型定义,为跨端项目中TS使用提供兼容支持;公共方法,沉淀高效公共方法便于快速交付;主题定义,应用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

需关注几点:
确认包引入:在package.json中确保包含@hlfe/ui@jdtaro/ui@nutui/icons-react-taro@nutui/nutui-react-taro等相关依赖。
确认配置项:回跨到iOS/安卓项目时,关注config/index.ts中的配置,避免编译异常,设置esnextModules包含相关模块。
组件使用:示例使用Popup组件:

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>
)

核心能力的优化

hlfe/ui的核心能力落在Taro基础组件与NutUI的跨端适配及能力建设上。在鸿蒙和回跨到iOS/安卓项目中,主要问题在于web和小程序端表现良好的布局与样式会以异常方式呈现,如弹框位置错误、Tabs切换白屏、SVG不支持等,需要逐一修改并推动上下游建设。

五端适配

区别于黄流业务的鸿蒙、iOS、安卓适配,基建需在兼容已有能力基础上实现新适配。Taro基建为无法支持的属性与API提供工具,可快速识别当前项目中在iOS与安卓上无法识别的能力。运行命令后,关注errors信息以解决阻塞编译的问题。解决时主要考虑:基础适配,如将web端标签改为Taro标签;兼容五端,通过判断端做不同处理;改进实现,规避不支持的属性或API;移除废弃API如getAppBaseInfo

能力扩充

为满足黄流项目精确需求,对部分组件进行了功能扩充:Popup组件支持拖拽变更半弹层高度和top属性展示营销位;SearchBar组件增加inputProps属性暴露更多input内置属性;Input组件增加style属性透传至native Input组件;Dialog组件底部按钮增加角标;CountDown组件支持千分位展示;Avatar组件支持图片填充模式;NoticeBar组件优化宽度获取逻辑。

无障碍支持

为更好回跨,APP侧输出统一无障碍规范,NutUI基于此进行完善。统一规范包括ariaRole、ariaLabel、ariaHidden、ariaChecked、ariaSelected、ariaRoledescription等属性。读取顺序为ariaLabel→value→ariaRole→hint组合朗读。当前实现中,大部分组件的View和Text读取正常,新增交互行为组件的无障碍属性如CheckBox、Radio等支持ariaLabel自定义。已知问题包括鸿蒙端弹层无法自动获取焦点,需手动触发可读取内容,影响Dialog、Toast、Popup等组件。

Icon库升级

Icon在组件中不可或缺,在鸿蒙/iOS/安卓适配中,采用Image src引入svg链接方式。实现难点在于推动主站SVG基建,如SVG展示、颜色变更、导出图片大小要求等。目前主站基建正向真实SVG落地,降低图片库导出成本。Icon库也补齐无障碍能力,方便开发者在icon使用时设置读取屏蔽或读取设置。例如在CheckBox组件中,Icon可禁用可读;在组件维度设置无障碍属性保障支持;在项目内可自定义ariaLabel或禁用读取。

回顾与总结

目前,@hlfe/ui已开放30+组件,持续支持订单鸿蒙、订单iOS/安卓回跨、商详鸿蒙、结算鸿蒙、购物车鸿蒙,并对商详、结算和购物车的回跨进行交付,未来将开放更多组件。回顾整个过程,是与业务侧、Taro侧、基建能力紧密协作的快速迭代历程。对于组件库与业务,都遇到一些痛点,希望在“提交issue-评审-提交PR-发布版本”的共建模式下,加快流程执行落地,快速响应业务诉求,为开发者提供更多共建可能性。

0 Answers