Skip to content

Conversation

@tutuxxx
Copy link
Member

@tutuxxx tutuxxx commented Nov 5, 2025

这个 PR 做了什么? (简要描述所做更改)

这个 PR 是什么类型? (至少选择一个)

  • 错误修复 (Bugfix) issue: fix #
  • [✅ ] 新功能 (Feature)
  • 代码重构 (Refactor)
  • TypeScript 类型定义修改 (Types)
  • 文档修改 (Docs)
  • 代码风格更新 (Code style update)
  • 构建优化 (Chore)
  • 其他,请描述 (Other, please describe):

这个 PR 涉及以下平台:

  • 所有平台
  • Web 端(H5)
  • 移动端(React-Native)
  • 鸿蒙(Harmony)
  • 鸿蒙容器(Harmony Hybrid)
  • ASCF 元服务
  • 快应用(QuickApp)
  • [ ✅] 所有小程序
  • 微信小程序
  • 企业微信小程序
  • 京东小程序
  • 百度小程序
  • 支付宝小程序
  • 支付宝 IOT 小程序
  • 钉钉小程序
  • QQ 小程序
  • 飞书小程序
  • 快手小程序
  • 头条小程序

Summary by CodeRabbit

发布说明

  • 新功能

    • 新增 componentsMap 公共配置路径,支持组件注入、别名与重复组件映射合并,提升组件复用与替换能力
  • Bug 修复

    • 过滤并隐藏内部重复标记,避免冗余属性在组件实例中暴露
  • 文档

    • 增强可访问性文档,新增 aria 属性示例并扩展 componentsMap、nestElements、voidComponents 与第三方组件使用指导

@tutuxxx tutuxxx added this to the 4.1.8 milestone Nov 5, 2025
@tutuxxx tutuxxx requested a review from Single-Dancer November 5, 2025 08:58
@coderabbitai
Copy link

coderabbitai bot commented Nov 5, 2025

Walkthrough

引入对 $duplicateFromComponent 的识别与过滤:在生成迷你组件和构建模板时跳过该 prop,并在存在复制来源时将内部组件节点名重映射为连字符形式;运行时在 onSetupClose 阶段合并 internalComponents 到公开组件条目。

Changes

Cohort / File(s) 变更摘要
共享库 - 模板处理
packages/shared/src/template.ts
在 createMiniComponents 中添加跳过属性列表以排除 $duplicateFromComponent;在 buildComponentTemplate 中若组件含 $duplicateFromComponent 则将组件 nodeName 重映射为 dashed 形式,改变模板生成控制流。
共享库 - 工具函数
packages/shared/src/utils.ts
在 getComponentsAlias 的属性过滤阶段排除 $duplicateFromComponent,保持其余 camelCase 转换与排序逻辑不变。
插件运行时注入
packages/taro-plugin-inject/src/index.ts
在 onSetupClose 流程中引入合并步骤:遇到组件含 $duplicateFromComponent 且对应 internalComponents 存在时,通过 Object.assign 将 internalComponents 数据合并到公开组件条目,然后调用 template.mergeComponents。新增对 hasOwn 的导入使用。
插件文档
packages/taro-plugin-inject/README.md
扩展并重命名文档章节(新增 componentsMap 并重排编号);在示例中加入无障碍属性(aria-role、aria-label、aria-hidden、aria-selected)及组件映射/复制使用示例和说明。

Sequence Diagram(s)

sequenceDiagram
    participant Config as 用户配置
    participant Plugin as 插件初始化 (onSetup)
    participant Template as 模板构建
    participant Utils as 属性过滤
    participant Runtime as onSetupClose 合并阶段

    Config->>Plugin: 提供组件配置 (可能含 $duplicateFromComponent)
    Plugin->>Template: 调用 buildComponentTemplate / createMiniComponents
    Template->>Utils: 请求属性过滤
    Utils-->>Template: 返回已移除 `$duplicateFromComponent` 的 prop 集合
    Template->>Template: 若存在 $duplicateFromComponent,重映射 nodeName 为 dashed 形式
    Plugin->>Runtime: 触发 onSetupClose
    Runtime->>Runtime: 遍历组件列表
    alt 组件含 $duplicateFromComponent 且 internalComponents 存在
        Runtime->>Runtime: Object.assign 合并 internalComponents -> 公共组件
    end
    Runtime->>Template: 调用 template.mergeComponents
    Runtime-->>Config: 完成组件合并与模板准备
Loading

Estimated code review effort

🎯 3 (中等) | ⏱️ ~35 分钟

可能需额外关注:

  • packages/shared/src/template.ts 的跳过列表与 nodeName 重映射实现(连字符转换与边界情况)。
  • packages/taro-plugin-inject/src/index.tsObject.assign 的合并顺序及与 template.mergeComponents 的交互。
  • packages/shared/src/utils.ts 的过滤位置对 camelCase 和排序行为的影响。
  • 文档示例是否与实现保持一致(README 的配置示例与字段说明)。

Suggested reviewers

  • yoyo837

Poem

🐰 复制来个小组件,跳过属性轻灵迁,
虚线名儿悄悄换,内部合并不费力,
文档添了无障碍,开发者笑开颜!

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题清晰准确地描述了主要变更:为小程序平台添加支持插入已有原生组件的副本组件功能。
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/inject_base_component

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cebfa01 and 2df2132.

📒 Files selected for processing (4)
  • packages/shared/src/template.ts (3 hunks)
  • packages/shared/src/utils.ts (1 hunks)
  • packages/taro-plugin-inject/README.md (4 hunks)
  • packages/taro-plugin-inject/src/index.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/shared/src/utils.ts
  • packages/shared/src/template.ts
  • packages/taro-plugin-inject/src/index.ts
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-09-05T18:40:45.775Z
Learnt from: ianzone
Repo: NervJS/taro PR: 18150
File: packages/taro-platform-harmony-hybrid/package.json:43-45
Timestamp: 2025-09-05T18:40:45.775Z
Learning: 在 tarojs/plugin-platform-harmony-hybrid 包中,tarojs/components-library-react、tarojs/components-library-solid 和 tarojs/components-library-vue3 必须作为直接依赖(dependencies)而不能作为 peer 依赖,因为插件源码中有对这些包的直接引用,包括 componentAdapter* getter 方法和 webpack 别名配置。

Applied to files:

  • packages/taro-plugin-inject/README.md
📚 Learning: 2025-05-25T18:02:31.387Z
Learnt from: ianzone
Repo: NervJS/taro PR: 17746
File: packages/taro-runtime/tsdown.config.ts:10-16
Timestamp: 2025-05-25T18:02:31.387Z
Learning: 在 taro-runtime 包的 tsdown 配置中,必须禁用 treeshake 来保留 dom-external/index.js 文件。

Applied to files:

  • packages/taro-plugin-inject/README.md
📚 Learning: 2025-08-08T02:32:58.265Z
Learnt from: ianzone
Repo: NervJS/taro PR: 18146
File: packages/babel-plugin-transform-react-jsx-to-rn-stylesheet/package.json:12-14
Timestamp: 2025-08-08T02:32:58.265Z
Learning: 在 Taro 项目的 pnpm 工作区中,Vitest 相关依赖(vitest 和 vitest/coverage-istanbul)被管理在根目录的 package.json 中,而不是各个子包的 devDependencies 中。这是 monorepo 中依赖提升的标准做法。

Applied to files:

  • packages/taro-plugin-inject/README.md
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: Build Rust Binding / stable - aarch64-apple-darwin
  • GitHub Check: Build Rust Binding / stable - x86_64-unknown-linux-gnu
  • GitHub Check: Build Rust Binding / stable - x86_64-pc-windows-msvc
  • GitHub Check: Build Rust Binding / stable - x86_64-apple-darwin
  • GitHub Check: Build Rust WASM / stable - wasm32-wasi
  • GitHub Check: Build Rust Binding / stable - aarch64-apple-darwin
  • GitHub Check: Build Rust Binding / stable - x86_64-unknown-linux-gnu
  • GitHub Check: Build Rust Binding / stable - x86_64-apple-darwin
  • GitHub Check: Build Rust Binding / stable - x86_64-pc-windows-msvc
  • GitHub Check: Build Rust WASM / stable - wasm32-wasi
🔇 Additional comments (3)
packages/taro-plugin-inject/README.md (3)

126-132: 新增无障碍属性配置

View 组件的无障碍属性配置添加得当,遵循了现有的属性定义模式。


173-177: 新增 componentsMap 部分清晰完整

第 4 部分新增了对 componentsMap 的详细说明,包括基础用法和副本组件的特殊用法,结构合理。


252-343: 部分编号调整正确

第 5、6、7 部分的编号重新排列正确,与新增的第 4 部分 componentsMap 相匹配。


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai bot requested a review from zhengyanan1 November 5, 2025 08:59
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/taro-plugin-inject/src/index.ts (1)

58-64: 建议增加输入验证和错误处理

组件合并逻辑实现基本正确,但建议增强健壮性:

  1. 类型验证$duplicateFromComponent 应验证为字符串类型
  2. 循环引用检测:如果组件 A 复制 B,B 复制 A,会导致问题
  3. 错误提示:当 $duplicateFromComponent 引用不存在的组件时,应提供明确的错误信息

建议应用以下改进:

         if (components) {
+          const processedKeys = new Set<string>()
           for (const key in components) {
             const { $duplicateFromComponent } = components[key] || {}
             const internalComponents = platform?.template?.internalComponents || {}
-            if (hasOwn(components, key) && $duplicateFromComponent && internalComponents[$duplicateFromComponent]) {
+            if (hasOwn(components, key) && $duplicateFromComponent) {
+              // 验证 $duplicateFromComponent 是字符串
+              if (typeof $duplicateFromComponent !== 'string') {
+                console.warn(`[taro warn] 组件 ${key} 的 $duplicateFromComponent 必须是字符串类型`)
+                continue
+              }
+              // 检查循环引用
+              if (processedKeys.has($duplicateFromComponent)) {
+                console.warn(`[taro warn] 检测到组件 ${key} 与 ${$duplicateFromComponent} 之间可能存在循环引用`)
+                continue
+              }
+              // 验证引用的组件存在
+              if (!internalComponents[$duplicateFromComponent]) {
+                console.warn(`[taro warn] 组件 ${key} 引用的 $duplicateFromComponent "${$duplicateFromComponent}" 不存在`)
+                continue
+              }
+              processedKeys.add(key)
               components[key] = Object.assign({}, internalComponents[$duplicateFromComponent], components[key])
             }
           }
packages/taro-plugin-inject/README.md (1)

214-250: 旧版本方案的差异说明不够清晰

提供旧版本的替代方案很有帮助,但建议补充说明新旧方案的区别:

  1. 4.1.8+ 版本(使用 $duplicateFromComponent):

    • 自动继承源组件的所有属性
    • 在模板生成阶段就确定了标签映射关系
    • 更安全、更易维护
  2. 4.1.8 以下版本(使用自定义插件):

    • 需要手动配置所有属性(不会自动继承 View 的属性)
    • 在构建产物阶段进行字符串替换
    • 需要额外的插件代码

建议在 Line 214 之后添加一段说明:

对于 4.1.8 以下的版本,可配合插件来实现类似的效果:

> **注意**:此方案与 4.1.8+ 的 `$duplicateFromComponent` 方案有本质区别。旧方案不会自动继承 View 组件的属性,需要在 `components` 配置中手动声明所有需要的属性。建议升级到 4.1.8+ 以使用更完善的实现。
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2acec67 and cebfa01.

📒 Files selected for processing (4)
  • packages/shared/src/template.ts (3 hunks)
  • packages/shared/src/utils.ts (1 hunks)
  • packages/taro-plugin-inject/README.md (4 hunks)
  • packages/taro-plugin-inject/src/index.ts (2 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-05-25T18:02:31.387Z
Learnt from: ianzone
Repo: NervJS/taro PR: 17746
File: packages/taro-runtime/tsdown.config.ts:10-16
Timestamp: 2025-05-25T18:02:31.387Z
Learning: 在 taro-runtime 包的 tsdown 配置中,必须禁用 treeshake 来保留 dom-external/index.js 文件。

Applied to files:

  • packages/taro-plugin-inject/src/index.ts
  • packages/taro-plugin-inject/README.md
📚 Learning: 2025-08-25T22:16:50.118Z
Learnt from: ianzone
Repo: NervJS/taro PR: 18150
File: packages/babel-plugin-transform-taroapi/tests/__mocks__/h5-definition.json:2356-2356
Timestamp: 2025-08-25T22:16:50.118Z
Learning: The file `packages/babel-plugin-transform-taroapi/tests/__mocks__/h5-definition.json` is auto-generated by the post-build script `packages/taro-platform-h5/scripts/post-build.mjs`, which copies content from `taro-platform-h5/dist/definition.json`. This file should not be manually edited.

Applied to files:

  • packages/taro-plugin-inject/src/index.ts
📚 Learning: 2025-09-05T18:40:45.775Z
Learnt from: ianzone
Repo: NervJS/taro PR: 18150
File: packages/taro-platform-harmony-hybrid/package.json:43-45
Timestamp: 2025-09-05T18:40:45.775Z
Learning: 在 tarojs/plugin-platform-harmony-hybrid 包中,tarojs/components-library-react、tarojs/components-library-solid 和 tarojs/components-library-vue3 必须作为直接依赖(dependencies)而不能作为 peer 依赖,因为插件源码中有对这些包的直接引用,包括 componentAdapter* getter 方法和 webpack 别名配置。

Applied to files:

  • packages/taro-plugin-inject/src/index.ts
  • packages/taro-plugin-inject/README.md
📚 Learning: 2025-08-08T02:32:58.265Z
Learnt from: ianzone
Repo: NervJS/taro PR: 18146
File: packages/babel-plugin-transform-react-jsx-to-rn-stylesheet/package.json:12-14
Timestamp: 2025-08-08T02:32:58.265Z
Learning: 在 Taro 项目的 pnpm 工作区中,Vitest 相关依赖(vitest 和 vitest/coverage-istanbul)被管理在根目录的 package.json 中,而不是各个子包的 devDependencies 中。这是 monorepo 中依赖提升的标准做法。

Applied to files:

  • packages/taro-plugin-inject/README.md
🧬 Code graph analysis (2)
packages/shared/src/template.ts (1)
packages/shared/src/utils.ts (4)
  • hasOwn (66-69)
  • capitalize (60-62)
  • toCamelCase (42-54)
  • toDashed (38-40)
packages/taro-plugin-inject/src/index.ts (1)
packages/shared/src/utils.ts (1)
  • hasOwn (66-69)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Build Rust Binding / stable - aarch64-apple-darwin
  • GitHub Check: Build Rust Binding / stable - x86_64-pc-windows-msvc
  • GitHub Check: Build Rust Binding / stable - x86_64-unknown-linux-gnu
  • GitHub Check: Build Rust Binding / stable - x86_64-apple-darwin
  • GitHub Check: Build Rust WASM / stable - wasm32-wasi
  • GitHub Check: Build Rust Binding / stable - aarch64-apple-darwin
  • GitHub Check: Build Rust Binding / stable - x86_64-pc-windows-msvc
  • GitHub Check: Build Rust Binding / stable - x86_64-apple-darwin
🔇 Additional comments (5)
packages/shared/src/utils.ts (1)

194-194: 正确过滤内部元数据属性

$duplicateFromComponent 添加到过滤列表中是正确的做法,确保这个内部配置不会被暴露为组件的实际属性。这与已有的 focusblur 过滤逻辑保持一致。

packages/taro-plugin-inject/src/index.ts (1)

4-4: LGTM - 正确引入工具函数

引入 hasOwn 用于属性存在性检查是合理的,避免了原型链污染问题。

packages/shared/src/template.ts (2)

142-156: 正确实现属性跳过机制

使用 skipProps 数组来排除 $duplicateFromComponent 是一个良好的设计:

  • 代码可扩展性强,便于未来添加更多需要跳过的属性
  • 在属性值转换之前就进行过滤,避免了不必要的处理
  • 与现有的 bind* 和事件处理逻辑保持一致

310-319: nodeName 重映射逻辑已验证为正确

经过验证,代码在以下三个方面均工作正常:

  1. 大小写转换链:正确将 comp.nodeName(dashed 格式)通过 toCamelCasecapitalize 转换后查找 internalComponents。例如 tab-index-viewTabIndexView

  2. 模板名称不受影响:模板名称使用 nodeAlias 而非 nodeName(见第 451 行 tmpl_${level}_${nodeAlias}),因此重映射不会改变模板名。

  3. 属性继承正确:当组件具有 $duplicateFromComponent 时,插件层(taro-plugin-inject 第 60-62 行)已在运行时合并了内部组件的属性,确保重映射后的标签使用完整属性。

该机制是插件系统的设计特性,允许自定义组件委托给原生组件。代码实现无误。

packages/taro-plugin-inject/README.md (1)

126-132: 良好的无障碍适配示例

为 View 组件添加 aria 属性的示例很有帮助,展示了 components 配置的实际应用场景。

@codecov
Copy link

codecov bot commented Nov 5, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 55.97%. Comparing base (3d0ba18) to head (2df2132).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff            @@
##             main   #18572    +/-   ##
========================================
  Coverage   55.97%   55.97%            
========================================
  Files         416      416            
  Lines       21563    21563            
  Branches     5301     5302     +1     
========================================
  Hits        12070    12070            
+ Misses       8012     7876   -136     
- Partials     1481     1617   +136     
Flag Coverage Δ
taro-cli 72.85% <ø> (ø)
taro-runtime 59.87% <ø> (ø)
taro-web 53.12% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.
see 43 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Single-Dancer Single-Dancer force-pushed the feat/inject_base_component branch from cebfa01 to 2df2132 Compare November 6, 2025 02:09
@coderabbitai coderabbitai bot requested a review from yoyo837 November 6, 2025 02:10
@Single-Dancer Single-Dancer merged commit 64195c5 into main Nov 6, 2025
39 checks passed
@Single-Dancer Single-Dancer deleted the feat/inject_base_component branch November 6, 2025 06:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants