-
Couldn't load subscription status.
- Fork 286
chore: 同步新增功能 #3374
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feat_v3.x
Are you sure you want to change the base?
chore: 同步新增功能 #3374
Conversation
Walkthrough此PR包含事件系统重构(Events转eventCenter)、Popup组件新增top支持、Dialog样式更新、Taro组件生命周期优化(useLayoutEffect→useReady)、50余个组件的样式dynamic条件编译添加,以及主题系统扩展。 Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes 变更涉及50+文件,包括结构化重构(NoticeBar、Swipe)、重复模式化修改(dynamic条件编译)和多类型编辑(样式、类型、Taro生命周期)。大量同构的条件编译块降低单项复杂度,但NoticeBar和Swipe的业务逻辑重构需要深度审查。 Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (4)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (2)
🧰 Additional context used🧬 Code graph analysis (1)src/utils/taro/get-rect-by-id.ts (1)
⏰ 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). (2)
🔇 Additional comments (1)
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 10
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/packages/swipe/swipe.taro.tsx (1)
149-160: 修正 toggle 中 opened 的判断同理,这里应使用
opened.current,否则开启阈值baseNum计算错误。- const baseNum = opened ? 1 - base : base + const baseNum = opened.current ? 1 - base : base
🧹 Nitpick comments (12)
src/packages/noticebar/demos/taro/demo10.tsx (1)
31-37: 文本截断样式实现正确。使用标准的 CSS 单行文本截断模式(overflow + whiteSpace + textOverflow),与
scrollable={false}配合实现静态展示效果。但需要注意:动态添加的项目(第 53 行)使用数字内容,无法演示文本截断效果,建议保持与初始数据相同的长文本格式以保证演示一致性。
可考虑修改动态添加逻辑:
<Button size="small" onClick={() => { - setList((prev) => [...prev, `${prev.length + 1}`]) + setList((prev) => [...prev, `新增项目 ${prev.length + 1}-公告栏公告栏公告栏公告栏`]) }} >src/hooks/taro/use-custom-event.ts (1)
6-7: 建议清理注释代码虽然将
customEvents更改为使用eventCenter是正确的架构改进(集中化事件管理),但建议删除第 6 行的注释代码。Git 历史已经保留了之前的实现,保留注释会增加代码噪音。应用此差异来清理注释代码:
import { eventCenter, getCurrentInstance } from '@tarojs/taro' import { useForceUpdate } from '@/hooks/use-force-update' -// export const customEvents = new Events() export const customEvents = eventCentersrc/packages/swipe/swipe.taro.tsx (3)
106-109: 在 TouchStart 中等待宽度测量,避免首帧越界/跳变未等待
getWidth()即开始计算,会在慢设备/异步测量下出现首次滑动边界不准。- nextTick(() => getWidth()) + nextTick(async () => { + await getWidth() + })或直接:
- getWidth() + await getWidth()
233-252: Taro 多端下直接使用 document 需加守卫小程序端无 DOM,直接读写
document可能报错。建议仅在 H5 生效或加类型守卫。- document.addEventListener('touchstart', handler) - return () => { - document.removeEventListener('touchstart', handler) - } + if (typeof document !== 'undefined' && document.addEventListener) { + document.addEventListener('touchstart', handler) + return () => document.removeEventListener('touchstart', handler) + } + return () => {}请在 Taro H5 与微信/支付宝小程序分别验证是否正常关闭。
99-105: 使用 translate3d 提升移动端渲染性能(可选)将
translate改为translate3d,更利于 GPU 合成。- transform: `translate(${state.offset}px, 0)`, + transform: `translate3d(${state.offset}px, 0, 0)`,src/sites/sites-react/doc/docs/react/migrate-from-v2.md (1)
99-103: 微调中文表述与排版建议在
title两侧加空格,且用“上方”更自然。-- 新增属性 top,用于在title上侧展示用户自定义内容 +- 新增属性 top,用于在 title 上方展示用户自定义内容src/packages/popup/popup.scss (1)
102-104: 为 bottom-top 区域补充定位与尺寸,避免覆盖/错位仅设置
position: absolute可能导致与标题/内容重叠;建议补齐定位与宽度。- &-top { - position: absolute; - } + &-top { + position: absolute; + top: 0; + left: 0; + width: 100%; + z-index: 1; + }请结合组件运行时为主体内容区域腾挪相应的 padding-top(可由 JS 计算 top 区域高度后设置)并在 H5/Taro 小程序端回归。
src/sites/sites-react/doc/docs/taro/migrate-from-v2.en-US.md (1)
99-103: 统一术语与句式(英文文档)将 attribute 改为 prop,简化句式,顺带避免重复 “Added …”。
-- Added a new attribute top to display user-defined content above the title. +- Added a top prop to display custom content above the title.src/utils/taro/get-rect-by-id.ts (1)
3-14: 建议提取共享的 ENV_TYPE 常量在多个文件中发现了相同的 ENV_TYPE 常量定义(此文件和
src/packages/input/input.taro.tsx)。建议将其提取到共享的工具文件中,避免代码重复。例如,可以创建
src/utils/taro/constants.ts:export const ENV_TYPE = { WEAPP: 'WEAPP', SWAN: 'SWAN', ALIPAY: 'ALIPAY', TT: 'TT', QQ: 'QQ', JD: 'JD', WEB: 'WEB', RN: 'RN', HARMONY: 'HARMONY', QUICKAPP: 'QUICKAPP', } as const然后在需要的地方导入使用:
import { ENV_TYPE } from '@/utils/taro/constants'src/packages/input/input.taro.tsx (1)
18-29: ENV_TYPE 常量重复定义此文件中的 ENV_TYPE 常量与
src/utils/taro/get-rect-by-id.ts中的定义完全相同。建议提取到共享工具文件中以避免代码重复。参考之前的建议,可以创建
src/utils/taro/constants.ts并在两个文件中导入使用。src/packages/noticebar/noticebar.taro.tsx (2)
164-171: 命名小误:warpRes → wrapRes当前变量名与“wrap”语义不一致,易读性下降。建议统一为 wrapRes:
- const warpRes = await getRectInMultiPlatform(wrapRef.current, wrapRefId) + const wrapRes = await getRectInMultiPlatform(wrapRef.current, wrapRefId) - if (!warpRes || !contentRes) return - const wrapW = warpRes.width + if (!wrapRes || !contentRes) return + const wrapW = wrapRes.width
145-148: 补充 initScrollWrap 的触发条件(可选)内容宽度与滚动判定也会受 align、scrollable、speed、RTL 等影响,建议扩展依赖:
- useEffect(() => { - initScrollWrap() - }, [content]) + useEffect(() => { + initScrollWrap() + }, [content, align, scrollable, speed, rtl])
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (62)
src/hooks/taro/use-custom-event.ts(1 hunks)src/packages/animatingnumbers/countup.scss(1 hunks)src/packages/avatarcropper/avatarcropper.taro.tsx(3 hunks)src/packages/badge/badge.scss(2 hunks)src/packages/button/button.scss(1 hunks)src/packages/cascader/cascader.scss(1 hunks)src/packages/checkbox/checkbox.scss(1 hunks)src/packages/checkbox/checkbox.taro.tsx(1 hunks)src/packages/checkbox/checkbox.tsx(1 hunks)src/packages/checkboxgroup/checkboxgroup.scss(1 hunks)src/packages/configprovider/types.ts(2 hunks)src/packages/dialog/demos/taro/demo6.tsx(1 hunks)src/packages/dialog/dialog.scss(3 hunks)src/packages/divider/divider.scss(1 hunks)src/packages/drag/drag.scss(1 hunks)src/packages/elevator/elevator.scss(2 hunks)src/packages/input/input.scss(0 hunks)src/packages/input/input.taro.tsx(2 hunks)src/packages/inputnumber/inputnumber.scss(1 hunks)src/packages/loading/loading.scss(1 hunks)src/packages/lottie/lottiemp.taro.tsx(3 hunks)src/packages/menuitem/menuitem.scss(1 hunks)src/packages/noticebar/demos/taro/demo10.tsx(3 hunks)src/packages/noticebar/noticebar.scss(1 hunks)src/packages/noticebar/noticebar.taro.tsx(12 hunks)src/packages/notify/notify.scss(1 hunks)src/packages/popup/doc.en-US.md(1 hunks)src/packages/popup/doc.md(1 hunks)src/packages/popup/doc.taro.md(1 hunks)src/packages/popup/popup.scss(1 hunks)src/packages/popup/popup.tsx(5 hunks)src/packages/radio/radio.scss(1 hunks)src/packages/range/range.taro.tsx(2 hunks)src/packages/rate/rate.scss(1 hunks)src/packages/rate/rate.taro.tsx(3 hunks)src/packages/resultpage/resultpage.scss(1 hunks)src/packages/searchbar/searchbar.scss(1 hunks)src/packages/segmented/segmented.scss(1 hunks)src/packages/sidebaritem/sidebaritem.scss(1 hunks)src/packages/signature/demo.scss(1 hunks)src/packages/skeleton/skeleton.scss(1 hunks)src/packages/steps/steps.scss(2 hunks)src/packages/swipe/swipe.taro.tsx(6 hunks)src/packages/switch/switch.scss(2 hunks)src/packages/tabpane/tabpane.scss(1 hunks)src/packages/tabs/tabs.scss(1 hunks)src/packages/tag/tag.scss(1 hunks)src/packages/textarea/textarea.taro.tsx(0 hunks)src/packages/timeselect/timeselect.scss(1 hunks)src/packages/toast/toast.scss(2 hunks)src/packages/toast/toast.taro.tsx(2 hunks)src/packages/virtuallist/virtuallist.scss(1 hunks)src/sites/sites-react/doc/docs/react/migrate-from-v2.en-US.md(1 hunks)src/sites/sites-react/doc/docs/react/migrate-from-v2.md(1 hunks)src/sites/sites-react/doc/docs/taro/migrate-from-v2.en-US.md(1 hunks)src/sites/sites-react/doc/docs/taro/migrate-from-v2.md(1 hunks)src/styles/theme-default.scss(2 hunks)src/styles/variables-jmapp.scss(3 hunks)src/styles/variables-jrkf.scss(3 hunks)src/styles/variables.scss(9 hunks)src/types/spec/popup/base.ts(1 hunks)src/utils/taro/get-rect-by-id.ts(1 hunks)
💤 Files with no reviewable changes (2)
- src/packages/input/input.scss
- src/packages/textarea/textarea.taro.tsx
🧰 Additional context used
🧬 Code graph analysis (4)
src/packages/range/range.taro.tsx (1)
src/utils/taro/get-rect.ts (1)
getRectInMultiPlatform(29-55)
src/packages/toast/toast.taro.tsx (1)
src/utils/taro/platform.ts (1)
td(16-18)
src/packages/swipe/swipe.taro.tsx (2)
src/utils/taro/get-rect.ts (1)
getRectInMultiPlatform(29-55)src/types/base/atoms.ts (1)
PositionX(42-42)
src/packages/noticebar/noticebar.taro.tsx (2)
src/hooks/use-uuid.ts (1)
useUuid(17-20)src/utils/taro/get-rect.ts (1)
getRectInMultiPlatform(29-55)
🪛 LanguageTool
src/sites/sites-react/doc/docs/react/migrate-from-v2.en-US.md
[style] ~101-~101: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ht, which can be used with resizable. - Added a new attribute top to display user-def...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
src/sites/sites-react/doc/docs/taro/migrate-from-v2.en-US.md
[style] ~101-~101: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ht, which can be used with resizable. - Added a new attribute top to display user-def...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
⏰ 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). (2)
- GitHub Check: test
- GitHub Check: build
🔇 Additional comments (78)
src/packages/inputnumber/inputnumber.scss (3)
2-7: 验证预处理器指令的用途和构建工具支持。代码引入了
/* #ifndef dynamic */和/* #ifdef dynamic */这样的条件编译指令。虽然这种模式在 C/C++ 中很常见,但在 SCSS 中需要明确说明:
- 构建工具支持:哪个构建工具或打包工具负责处理这些预处理器指令?是 Taro、Webpack、PostCSS 插件还是自定义工具?
- dynamic 标志用途:这个标志何时被定义?在哪些场景或构建配置中使用?
- 布局影响:从
inline-flex切换到flex的语义差异是什么?这对组件的布局和渲染会产生什么影响?
9-10: 澄清宽度计算的格式调整。第 9-10 行的宽度计算被重新格式化为两行。虽然这是一个较小的改变,但请确认:
- 这是否与主要的 display 属性条件编译相关?
- 或者这只是代码格式的优化?
2-11: 验证测试覆盖和相关配置变更。这个改动引入了构建时的条件逻辑。请确认:
- 是否存在针对
dynamic和非dynamic两种情况的测试覆盖?- 是否在构建配置(如
package.json,tsconfig.json或 Taro 配置)中添加了对应的标志定义?- 此改动是否相关于 PR 标题中提到的"同步新增功能"?如果是,请在 PR 描述中补充相关背景信息。
src/packages/animatingnumbers/countup.scss (1)
3-8: 动态/非动态构建切换的条件指令使用正确。预处理器指令格式规范,互斥条件清晰。非动态模式下使用
inline-flex,动态模式下切换为flex,逻辑合理。该模式与 PR 中其他组件(如 badge、checkboxgroup、divider 等)的模式一致,符合预期的构建变体切换规范。src/packages/steps/steps.scss (2)
117-122: 确认自定义预处理器配置此处使用的
#ifndef dynamic和#ifdef dynamic指令为注释形式,依赖自定义构建工具进行条件编译处理。需要确认:
- 项目构建系统已正确配置以处理这些预处理指令
- 如果指令未被处理,最终 CSS 中将同时出现两个
display声明,后者会覆盖前者建议验证完整的构建流程以确保这些条件分支能够正确解析。
240-242: 验证单一守卫的语义此处仅使用
#ifndef dynamic保护overflow: auto;属性,与前面的双值守卫模式(117-122行)不同。这意味着:
- 未定义
dynamic时:应用overflow: auto;- 定义
dynamic时:该属性被省略请确认在动态模式下
overflow行为是否由其他样式规则控制,或确实应该省略此属性。建议补充对应的#ifdef dynamic块以明确双路径逻辑(即便该路径为空)。src/packages/tabs/tabs.scss (2)
113-115: 验证自定义预处理器指令的处理代码使用 CSS 注释形式的预处理器指令
/* #ifndef dynamic*/来条件性地包含overflow: unset;。这种模式非标准,通常需要自定义构建工具处理。请确认以下事项:
- 构建系统(webpack/rollup/其他)是否配置了处理这些注释指令的预处理器或插件?
- 这些指令在最终编译后的 CSS 中是否会被正确移除(在 dynamic 定义时)或保留(在 dynamic 未定义时)?
- 这种模式是否已在项目中的其他文件中验证过有效性?
如果您想,我可以生成一个脚本来搜索其他使用此模式的文件,确认一致性。
123-125: 模式一致性良好与第 113-115 行一致,此段代码使用相同的预处理器指令模式。两处修改都在活跃状态选择器中,统一地应用了条件性
overflow: unset;。SCSS 语法本身没有问题。src/packages/noticebar/demos/taro/demo10.tsx (2)
6-9: 数据更新合理。扩展文本长度用于演示文本截断效果,与新增的样式功能配合良好。
20-20: 验证 scrollable={false} 的行为变更。将
scrollable设置为false会改变垂直公告栏的滚动行为,请确认这是演示预期的功能效果(静态展示 + 文本截断)。src/packages/lottie/lottiemp.taro.tsx (3)
1-2: 引入 useReady 生命周期钩子符合 Taro 最佳实践。将初始化逻辑从
useLayoutEffect迁移到useReady是正确的做法,这是 Taro 为小程序环境提供的专用生命周期钩子,确保在页面准备就绪后再执行 canvas 初始化操作。
23-28: 验证 speed 属性的响应式行为。
setSpeed函数的逻辑正确,使用Math.abs(speed)设置速度值,并根据正负号设置播放方向。但是,该函数仅在动画初始化时调用一次(第 67 行),如果speed属性在组件挂载后发生变化,动画速度不会更新。请确认
speed属性是否需要支持动态更新。如果需要,应添加一个 effect 来监听speed的变化并调用setSpeed()。如需支持动态 speed,可参考以下实现:
// 在 useReady 之后添加 useEffect(() => { setSpeed() }, [speed])Also applies to: 67-67
31-75: useReady 钩子使用正确。初始化逻辑正确地封装在
useReady钩子中,包括 canvas 查询、Lottie 动画加载、事件监听器绑定以及速度设置。错误处理也已到位。这符合 Taro 小程序的开发规范。src/packages/rate/rate.taro.tsx (3)
10-10: LGTM!正确引入 Taro 生命周期钩子。使用
useReady替代 React 的useLayoutEffect是 Taro 小程序环境的最佳实践,能确保在页面完全准备好后执行初始化逻辑。
134-143: 移除 useCallback 是可接受的简化。将
updateRects从useCallback包裹的函数改为普通函数在功能上是正确的,因为该函数只在useReady和handleTouchStart中直接调用,未作为依赖项传递。虽然每次渲染都会重新创建函数实例,但性能影响微乎其微,代码反而更简洁。
145-147: 优秀的 Taro 生命周期适配!使用
useReady替代useLayoutEffect是针对 Taro 小程序环境的正确做法:
useLayoutEffect在小程序环境中可能无法按预期工作useReady确保在 Taro 页面完全就绪后执行,此时 refs 已正确填充- 配合
handleTouchStart中的updateRects()调用(第 157 行),在用户交互时也能更新尺寸信息这一改动与 Taro 4.0.12 的最佳实践保持一致。
src/packages/virtuallist/virtuallist.scss (1)
38-40: 这些预处理指令不被构建系统处理,是无效的 CSS 注释。虽然
/* #ifndef dynamic*/和/* #ifdef */指令确实在项目中广泛使用(button、badge、animatingnumbers、address、virtuallist 等多个组件都有此模式),但构建系统并未处理它们。package.json 中仅配置了标准 Sass 和 PostCSS 工具,没有任何自定义预处理器插件来解析这些指令。因此,这些指令仅作为普通 CSS 注释被忽略,不产生任何条件编译效果。这可能表示:
- 该模式是遗留代码或来自前一个构建系统
- 项目计划支持但尚未实现的功能
- 对 SCSS 条件语法(应使用
@if/@else)的误解建议: 如这些指令无实际用途,应从 virtuallist.scss 及整个项目中移除;或澄清它们是否为未来功能的占位符。
src/packages/timeselect/timeselect.scss (1)
19-21: 澄清非标准 CSS 预处理器指令的用途——该模式缺乏构建工具支持证据。验证确认了这些
/* #ifndef dynamic*/和/* #endif */注释在代码库中被广泛使用(badge、elevator、noticebar、input 以及 20+ 个其他组件),但以下问题仍未解决:
无可见的构建工具支持:检查的 vite.config.site.mts 采用标准 SCSS 编译(
modern-compilerAPI、postcss-import),但不包含处理这些 CSS 注释指令的自定义插件。注释将被按字面意思编译:SCSS 编译器不处理这些指令;它们最终会作为字面 CSS 注释出现在编译后的 CSS 文件中,不影响样式。
用途不明确:代码库中未找到关于"dynamic"标志用途的文档;这些指令似乎要么是遗留代码,要么由未在 vite 配置中显示的后处理工具处理。
建议开发者验证并补充说明:
- 这些指令是否由某个专用的后处理工具处理(如自定义 webpack 插件、构建脚本)?
- "dynamic"标志的确切用途是什么?
- 这个模式是否仍在维护,还是遗留代码?
src/packages/toast/toast.taro.tsx (1)
16-16: 引入平台检测工具函数正确引入了
td函数用于后续的动态平台渲染判断,与现有的harmony引入保持一致。src/packages/toast/toast.scss (2)
99-102: 动态平台样式适配为 harmony dynamic 平台添加了
line-height: normal和height: auto覆盖,与 TypeScript 文件中使用Text组件的条件渲染逻辑配合良好,有助于文本在不同平台下的正确显示。
111-113: 确认样式差异是否有意为之注意到
.nut-toast-title的 harmony dynamic 块中仅添加了line-height: normal,而未像.nut-toast-text(第 99-102 行)那样同时添加height: auto。请确认这种差异是有意设计还是遗漏。如果 title 也应该自适应高度,建议补充height: auto。src/packages/cascader/cascader.scss (1)
14-16: 验证动态编译指令的构建系统支持。此文件使用注释风格的预处理指令(
/* #ifndef dynamic*/等)来条件编译CSS属性。需要确认构建系统是否正确支持并处理这些指令。建议补充构建配置文档说明如何启用/禁用"dynamic"模式。src/packages/rate/rate.scss (1)
100-105: 确认 display 属性切换对布局的影响。在动态模式下,
display: inline-flex改为display: flex,这会改变评分组件相对于其他内联元素的布局行为。需要确保此改动在预期的使用场景中不会导致意外的页面布局变化,特别是在包含评分组件的行内上下文中。src/packages/sidebaritem/sidebaritem.scss (1)
10-12: 验证 overflow 属性移除对滚动行为的影响。在动态模式下,
overflow: auto会被完全移除。需要确保侧边栏项目内容超出容器时,动态模式下有适当的滚动处理机制或无此需求。建议在具体的使用场景中测试此改动。src/packages/skeleton/skeleton.scss (1)
7-12: 确认动态模式下骨架屏布局的一致性。骨架屏内容在动态模式下从
inline-flex变为flex。需要确保此改动不会导致骨架屏加载状态与实际加载后内容的布局差异,特别是在内联上下文中。src/packages/segmented/segmented.scss (1)
2-7: 验证分段控制器在动态模式下的呈现行为。分段控制组件在动态模式下从
display: inline-flex改为display: flex。请确认此改动在各种容器上下文(例如表单、工具栏、内联布局)中的表现符合预期,避免出现意外的换行或布局破损。src/packages/drag/drag.scss (1)
10-15: 验证动态模式下拖拽元素的尺寸计算。拖拽内部元素在动态模式下从
display: inline-flex变为display: flex。需要确保此改动不会影响被拖拽元素的fit-content尺寸计算和拖拽操作的流畅性。建议在实际拖拽场景中验证。src/packages/signature/demo.scss (1)
16-21: 验证 demo 文件中的样式改动。这是演示页面的样式改动,与实际组件功能无关。确保此改动仅影响演示UI,不会对签名组件本身的功能或布局造成影响。
src/packages/divider/divider.scss (1)
48-53: 确认垂直分隔线在动态模式下的对齐行为。垂直分隔线在动态模式下从
display: inline-flex改为display: flex。需要确保此改动不会导致垂直分隔线与水平布局中其他元素的对齐问题,尤其是在涉及vertical-align: middle的场景中。src/packages/tabpane/tabpane.scss (1)
9-11: 自定义预处理器指令需要构建系统支持这些注释形式的条件编译块(
/* #ifndef dynamic*/等)需要在构建过程中被正确处理,否则将以注释形式保留在最终的 CSS 中。请确认你的构建工具链支持这类指令的解析。src/packages/tag/tag.scss (1)
65-70: 动态构建标志使用一致,需构建系统验证这个文件遵循了 PR 中的一致模式,使用条件编译块切换
display属性。请确认你的构建流程能够正确识别并处理这些#ifndef和#ifdef指令。src/packages/switch/switch.scss (1)
4-9: 多个条件块的处理需验证此文件中两个独立的条件编译块(根元素和标签元素)都使用了动态标志。请确保你的构建系统能够正确处理同一文件中的多个
#ifndef dynamic块。Also applies to: 66-71
src/packages/noticebar/noticebar.scss (1)
39-47: 使用initial关键字存在潜在布局风险与其他组件不同,这个文件使用
display: initial和flex: initial,这会将这些属性重置为浏览器默认值(inline和0 1 auto)。这可能会在非动态构建中破坏 flex 容器布局。请验证在两种构建模式下布局行为是否符合预期,并确保initial关键字的浏览器兼容性满足要求。src/packages/notify/notify.scss (1)
76-84: 条件编译模式一致,需构建系统验证此文件对图标元素使用了条件编译块。请确认构建工具能正确处理这些动态标志。
src/packages/checkboxgroup/checkboxgroup.scss (1)
32-39: 水平布局的条件编译应用正确,需构建系统验证针对水平排列模式的复选框元素应用了条件编译块。请确保构建系统能正确处理此指令。
src/packages/resultpage/resultpage.scss (1)
8-20: 图标显示属性的条件编译应用标准,需构建系统验证此文件对结果页面的图标元素使用了条件编译块切换显示属性。请确认构建工具支持该指令。
src/packages/loading/loading.scss (1)
2-7: 根级别条件编译应用标准,需构建系统验证此文件在根组件级别应用了条件编译块。请确保构建系统能正确处理该指令,且不影响加载动画等其他功能。
src/packages/avatarcropper/avatarcropper.taro.tsx (2)
696-696: 与 AI 摘要不一致AI 摘要中提到移除了
AvatarCropper.displayName的赋值,但在提供的代码中第 696 行仍然保留了该赋值。请确认是否需要移除此行以保持与其他更改的一致性。
140-152: 原始审查评论基于对 Taro 生命周期的错误理解,代码实现实际上是正确的Taro 的
useReady仅在页面的 onReady 生命周期触发时执行一次,不会在返回页面时重新执行。返回页面会触发 onShow/useDidShow,而非 onReady/useReady。审查评论声称"useReady 在每次页面显示时都会执行(包括从后台切换回来)",但这是错误的。代码中的 useReady 模式:
- 在页面首次加载时执行一次
- 自动获取 Alipay Canvas2D 节点引用
- 与同一代码库的其他组件(swipe、rate、range、lottie)保持一致
不需要添加标志位来防止重复执行,因为 Taro 本身已确保 useReady 的单次执行。
Likely an incorrect or invalid review comment.
src/packages/menuitem/menuitem.scss (1)
31-41: LGTM!条件编译块的使用正确,与 PR 中其他组件(badge.scss、elevator.scss 等)的模式保持一致。这允许在动态构建模式下使用
flex而在常规模式下使用inline-flex。src/packages/range/range.taro.tsx (1)
289-299: useReady + nextTick 的组合使用合理使用
nextTick延迟 rect 测量是正确的做法,确保 DOM 已经渲染完成。这比之前的useLayoutEffect更符合 Taro 的生命周期模型。不过同样需要注意
useReady在页面每次显示时都会执行,请确认是否需要添加逻辑来避免重复测量。根据学习内容,建议在升级后针对各平台(微信、支付宝、京东、H5)进行全面测试。
src/packages/elevator/elevator.scss (2)
19-21: 验证移除 overflow 的影响在
dynamic模式下移除了overflow: auto,这可能会影响滚动行为。请确保在动态构建环境中测试了电梯组件的滚动功能,特别是在内容超出容器高度时的表现。
100-106: LGTM!条件编译模式与其他组件保持一致,在
dynamic模式下使用flex,在常规模式下使用inline-flex。src/packages/badge/badge.scss (1)
1-51: LGTM!Badge 组件的条件编译实现正确,与 PR 中其他组件保持一致。在基础类和
&-sup变体中都正确应用了dynamic标志的判断。src/styles/variables-jrkf.scss (2)
129-129: LGTM!新增的
$font-weight-medium变量定义合理,默认值 500 符合中等字重的标准。这扩展了主题定制能力。
1617-1640: LGTM!新增的 Dialog 相关变量(
$dialog-title-margin-bottom和$dialog-footer-button-border)提供了更细粒度的样式控制。默认值(8px 和 6px)符合设计系统规范。这些变量已在
src/packages/configprovider/types.ts中添加了对应的类型定义,保持了一致性。根据相关上下文,这些变量也在 theme-default.scss 和 variables.scss 中有相应定义。
src/packages/configprovider/types.ts (2)
59-66: LGTM!新增的 CSS 变量类型定义(
nutuiFontSizeIcon和nutuiFontWeightMedium)与主题变量文件中的定义保持一致,扩展了类型安全的主题定制能力。
464-469: LGTM!Dialog 相关的 CSS 变量类型(
nutuiDialogTitleMarginBottom和nutuiDialogFooterButtonBorder)与 variables-jrkf.scss 中新增的变量相对应,保持了类型定义的完整性。根据相关上下文,这些变量也在 theme-default.scss 和 variables.scss 中有定义。
src/hooks/taro/use-custom-event.ts (1)
7-7: 评论已验证并确认无需改动迁移到
eventCenter是安全的。验证结果:
- 事件隔离性:✓ 通过
${routerPath}__${selector}命名规则确保唯一性,已在 toast/dialog/notify 中验证- API 兼容性:✓
eventCenter是 Taro 官方全局事件中心,完全支持代码中使用的on/off/trigger方法- 内存泄漏防护:✓ 在
useCustomEvent的 useEffect 中正确实现了清理函数调用off()该迁移符合 Taro 官方设计,代码实现完整无误。
src/types/spec/popup/base.ts (1)
18-22: 接口扩展合理,保持向后兼容新增
top?: ReactNode与文档、样式变更一致,无破坏性修改。src/packages/checkbox/checkbox.tsx (1)
206-206: 代码变更符合预期。新增的
${classPrefix}-active类在 checkbox 被选中时应用,为选中状态提供样式钩子。实现简洁且与 Taro 版本保持一致。src/packages/radio/radio.scss (1)
52-57: 条件编译指令实现正确。新增的动态构建守卫为 radio 按钮提供了构建时的布局切换能力(非动态构建使用
inline-flex,动态构建使用flex),与项目中其他组件的模式保持一致。src/packages/checkbox/checkbox.taro.tsx (1)
201-201: LGTM!Taro 版本的实现与 Web 版本保持一致,正确添加了选中状态的样式类。
src/sites/sites-react/doc/docs/react/migrate-from-v2.en-US.md (1)
101-101: 文档更新准确。清晰地记录了 Popup 组件新增的
top属性,说明其用途是在标题上方显示用户自定义内容。src/packages/popup/doc.md (1)
94-94: 属性文档完整且格式正确。新增的
top属性文档清晰记录了类型和用途,格式与其他属性保持一致。src/packages/popup/doc.en-US.md (1)
94-94: 英文文档正确且清晰。
top属性的英文文档与中文版本保持一致,描述清晰。src/sites/sites-react/doc/docs/taro/migrate-from-v2.md (1)
101-101: 迁移文档准确完整。清晰记录了 Popup 组件新增的
top属性及其用途,有助于用户从 v2 升级到 v3。src/packages/checkbox/checkbox.scss (1)
68-73: 条件编译样式看起来正确使用预处理器注释实现的条件编译语法正确,根据
dynamic标志切换 display 属性(inline-flex vs flex)的逻辑清晰。src/packages/button/button.scss (1)
58-60: 条件编译的 pointer-events 设置合理在 dynamic 构建模式下为
::before伪元素添加pointer-events: none是合理的,可以防止遮罩层捕获指针事件,确保按钮交互正常工作。src/packages/dialog/dialog.scss (4)
22-26: 条件编译注释已添加在 transition 属性周围添加了
/* #ifndef dynamic */和/* #endif */条件编译注释,与 PR 中其他组件的模式保持一致。
88-88: 标题下边距已更新为使用新变量使用
$dialog-title-margin-bottom变量替代硬编码值,提高了可维护性和主题定制能力。
131-132: 对话框底部按钮样式已增强添加了
border-radius和padding属性,使用 CSS 变量提供了更好的主题定制支持。
147-149: 确认按钮字体粗细已调整将 OK 按钮的 font-weight 从
$font-weight-bold(600) 改为$font-weight-medium(500),这是一个视觉设计调整。请确认此更改符合设计规范要求。src/styles/theme-default.scss (2)
276-277: 新增中等字重令牌添加了
--nutui-font-weight-medium: 500,为字体粗细提供了更细粒度的控制选项。这与其他文件中的相关更新保持一致。
262-263: 字体大小令牌更新存在主题不一致问题,需要修正验证发现
--nutui-font-size-l的更改在主题间不一致:
theme-default.scss(第262行):已更新为var(--nutui-font-size-15)(15px)theme-dark.scss(第263行):仍为var(--nutui-font-size-16)(16px)受影响的组件(使用
$font-size-l):
src/packages/toast/toast.scsssrc/packages/shortpassword/shortpassword.scsssrc/packages/price/price.scsssrc/packages/empty/empty.scss新增的
--nutui-font-size-icon令牌在variables.scss中已正确定义。建议:同步更新
theme-dark.scss第263行,保持两个主题的一致性。src/styles/variables-jmapp.scss (3)
106-106: 新增中等字重变量添加了
$font-weight-medium变量,默认值为 500,与主题令牌保持一致,为字体粗细提供了更多选择。
1504-1507: 新增对话框标题下边距变量添加了
$dialog-title-margin-bottom变量(默认 8px),提供了对话框标题间距的主题定制能力。
1524-1527: 新增对话框底部按钮圆角变量添加了
$dialog-footer-button-border变量(默认 6px),使对话框按钮的圆角可以通过主题进行定制。src/styles/variables.scss (9)
155-156: 字体大小令牌已更新
$font-size-l从 16px 调整为 15px,同时新增了$font-size-icon: 16px。这与theme-default.scss中的更改保持一致。请参考
theme-default.scss的评审意见,验证此更改对使用这些令牌的组件的影响。
165-165: 新增中等字重变量添加了
$font-weight-medium: 500,为字体粗细提供了更细粒度的控制。
598-598: 输入框行高已更新
$input-lineheight现在使用$font-size-xl而不是之前的值,这可能会影响输入框的垂直对齐。请确认此更改符合设计规范。
1084-1084: 弹出层标题字体大小已更新
$popup-title-font-size从$font-size-l更改为$font-size-xl,由于 font-size-l 本身也减小了 1px,这个更改会使标题更大。请验证视觉效果是否符合预期。
1397-1401: 对话框标题和内容间距变量已添加新增了
$dialog-title-margin-bottom(8px) 并更新了$dialog-content-margin(0 0 20px 0),提供了更好的间距控制。这些变量与 dialog.scss 和 variables-jmapp.scss 中的更改保持一致。
1414-1417: 对话框底部按钮圆角变量已添加新增了
$dialog-footer-button-border: 6px,为对话框底部按钮提供了圆角定制能力。
1436-1436: 对话框标题字体大小已更新
$dialog-header-font-size从$font-size-l更改为$font-size-xl。考虑到 font-size-l 减小了,这个更改会使对话框标题更大。请验证是否符合设计意图。
1477-1477: 复选框图标字体大小使用新令牌
$checkbox-icon-font-size现在使用$font-size-icon(16px) 而不是$font-size-l(15px),图标会稍微大一些。
1516-1519: 单选框图标字体大小使用新令牌
$radio-icon-font-size现在使用$font-size-icon(16px),与复选框的更改保持一致。src/packages/input/input.taro.tsx (1)
211-211: 验证disabled属性变更与其他 Taro 组件的一致性在
input.taro.tsx中,disabled属性仅传递disabled,但readOnly未被传入原生TaroInput组件,这意味着 readonly 输入框不再完全禁用交互。需要注意的是,同一库中的其他 Taro 组件(如
searchbar.taro.tsx第 184、203 行,textarea.taro.tsx第 131 行)仍然使用disabled={disabled || readOnly}的模式。此变更创建了库内的不一致性。建议验证:
- readonly 输入框行为变更是否为有意为之
- 是否有现存代码依赖于 readonly 使输入框完全禁用
- 是否应与其他 Taro 组件保持一致
| onClose={() => { | ||
| setVisible2(false) | ||
| console.log('关闭底部icon 3') | ||
| }} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
请移除调试日志,并考虑与第一个对话框保持一致性
添加 onClose 处理器来响应关闭图标的点击是合理的,但存在以下问题:
- 调试代码残留:第 45 行的
console.log('关闭底部icon 3')看起来像是调试代码,不应该保留在演示代码中 - 不一致性:第一个对话框(第 15-28 行)同样设置了
closeIcon,但没有onClose处理器。请确认这种差异是否是有意为之,用于演示不同的用法
应用此修改以移除调试日志:
onClose={() => {
setVisible2(false)
- console.log('关闭底部icon 3')
}}如果希望保持两个对话框的一致性,可以考虑为第一个对话框也添加 onClose 处理器:
<Dialog
className="test-dialog"
title="顶部带关闭按钮"
visible={visible1}
closeIcon
closeIconPosition="top-right"
style={{
'--nutui-dialog-close-color': '#888B94',
}}
onConfirm={() => setVisible1(false)}
onCancel={() => setVisible1(false)}
+ onClose={() => setVisible1(false)}
>
支持函数调用和组件调用两种方式。
</Dialog>🏁 Script executed:
#!/bin/bash
# 查看完整的演示文件内容,特别是两个 Dialog 组件的定义
cat src/packages/dialog/demos/taro/demo6.tsxLength of output: 1263
🏁 Script executed:
#!/bin/bash
# 检查项目中是否有类似的 console.log 用法模式
rg "console\.log\(" src/packages/dialog/demos/ -n -B2 -A2 | head -50Length of output: 1998
🏁 Script executed:
#!/bin/bash
# 检查文件中是否有其他中文日志,用于判断是否是有意的演示代码
rg "console\.(log|warn|error)" src/packages/dialog/demos/taro/ -nLength of output: 159
移除调试日志,并建议与第一个对话框保持一致
通过验证完整文件内容确认:
-
调试代码需要删除:第45行的
console.log('关闭底部icon 3')是中文调试信息,不应保留在演示代码中。相比之下,项目中其他demo文件使用的console.log(如'stop close'或'onClose')都是英文功能描述,而此处的中文信息明显是内部调试遗留。 -
两个Dialog的不一致性:
- 第一个Dialog(第15-28行):有
closeIcon但无onClose处理器 - 第二个Dialog(第35-50行):既有
closeIcon又有onClose处理器
建议保持一致,为两个Dialog都添加
onClose处理器,使演示代码更清晰完整。 - 第一个Dialog(第15-28行):有
建议修改:
移除第45行的调试日志:
onClose={() => {
setVisible2(false)
- console.log('关闭底部icon 3')
}}同时为第一个Dialog添加 onClose 处理器以保持一致:
<Dialog
className="test-dialog"
title="顶部带关闭按钮"
visible={visible1}
closeIcon
closeIconPosition="top-right"
style={{
'--nutui-dialog-close-color': '#888B94',
}}
onConfirm={() => setVisible1(false)}
onCancel={() => setVisible1(false)}
+ onClose={() => setVisible1(false)}
>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| onClose={() => { | |
| setVisible2(false) | |
| console.log('关闭底部icon 3') | |
| }} | |
| onClose={() => { | |
| setVisible2(false) | |
| }} |
🤖 Prompt for AI Agents
In src/packages/dialog/demos/taro/demo6.tsx around lines 43-46 (and also note
the first Dialog at lines 15-28), remove the debugging statement
console.log('关闭底部icon 3') and add an onClose handler to the first Dialog so both
Dialogs are consistent; the onClose handlers should mirror each other (set the
corresponding visible state to false) and avoid any debug-only console output.
| useState, | ||
| useCallback, | ||
| } from 'react' | ||
| import { nextTick } from '@tarojs/taro' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
用 nextTick + 基于 id 的多端测量重构很赞
- 使用 useUuid 生成 wrap/content 唯一 id 并配合 getRectInMultiPlatform,解决了小程序端无法直接用 ref 测量的问题;
- nextTick 保证节点挂载后再测量,减少空 rect 的概率;
- 横向场景只在可滚动时启动画动,逻辑清晰。
建议:
- 在 H5 与各小程序端各跑一次 smoke(测量为空、重复初始化等);
- 对于 RTL/align/scrollable/speed 等会影响宽度或滚动判定的 props,适当扩展触发 initScrollWrap 的依赖,避免遗漏重算。
我可提供简单用例矩阵以在 CI 执行。基于 Learnings(Taro 4.0.12 建议用统一 API 并保持多包对齐)。
Also applies to: 13-13, 73-76, 155-183, 505-510
🏁 Script executed:
#!/bin/bash
# 粗验初始化触发点,关注依赖项是否包含关键 props
rg -nP 'useEffect\(\s*\(\)\s*=>\s*{\s*initScrollWrap' src/packages/noticebar/noticebar.taro.tsx -C3Length of output: 0
搜索结果中未找到 getRectInMultiPlatform 的具体文档。我需要先审视原始文件内容,理解代码结构和依赖问题。
🏁 Script executed:
#!/bin/bash
# 查看文件前 100 行,定位关键函数和 import
head -100 src/packages/noticebar/noticebar.taro.tsxLength of output: 2622
🏁 Script executed:
#!/bin/bash
# 搜索 initScrollWrap 的定义
rg -n 'initScrollWrap' src/packages/noticebar/noticebar.taro.tsx -B2 -A5Length of output: 551
🏁 Script executed:
#!/bin/bash
# 搜索所有 useEffect 及其依赖
rg -n 'useEffect' src/packages/noticebar/noticebar.taro.tsx -B1 -A6Length of output: 1147
🏁 Script executed:
#!/bin/bash
# 搜索 handleClickIcon 的定义和实现
rg -n 'handleClickIcon' src/packages/noticebar/noticebar.taro.tsx -B2 -A10Length of output: 1021
修复 handleClickIcon 的关闭逻辑和补充 initScrollWrap 依赖
发现两处需要修复的问题:
-
行 219-227
handleClickIcon语义错误:
当前setShowNoticeBar(!closeable)导致逻辑反向。当closeable=false时,!closeable=true 会显示通知栏(无法真正关闭),违反预期。应改为setShowNoticeBar(false)或添加条件判断if (closeable)后才调用onClose,避免 closeable=false 时仍然触发关闭回调。 -
行 128-142 首个
useEffect依赖不完整:
当前依赖仅包含[isVertical, children, list],缺少direction、align、scrollable、speed、wrap等会影响滚动判定的 props。当这些 props 变化时无法触发initScrollWrap重算,可能导致测量结果过期。建议补充完整依赖。
🤖 Prompt for AI Agents
In src/packages/noticebar/noticebar.taro.tsx around lines 219-227, fix the close
logic by changing the toggle to explicitly hide the bar and only invoke the
onClose callback when the component is actually closeable (call
setShowNoticeBar(false) and if (closeable) onClose?.()). In
src/packages/noticebar/noticebar.taro.tsx around lines 128-142, update the first
useEffect dependency array to include all props that affect scroll computation —
add direction, align, scrollable, speed, wrap (and any other props used in
initScrollWrap) so initScrollWrap reruns when those change.
| const handleClickIcon = useCallback( | ||
| (event: ITouchEvent) => { | ||
| event.stopPropagation() | ||
| setShowNoticeBar(!closeable) | ||
| close && close(event) | ||
| onClose && onClose(event) | ||
| }, | ||
| [close, onClose, closeable] | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
右侧图标点击语义不当:在不可关闭时也触发 onClose,且会把条目“强制显示”
现实现为:
- setShowNoticeBar(!closeable):closeable=false 时点击会将其设为 true;
- 无论 closeable 与否,都会调用 close/onClose。
期望:
- 仅在 closeable=true 时关闭并触发 onClose;
- closeable=false 且存在自定义 rightIcon 时,点击应透传为普通点击(或触发 click/onClick),不改变显隐。
修复建议:
- const handleClickIcon = useCallback(
- (event: ITouchEvent) => {
- event.stopPropagation()
- setShowNoticeBar(!closeable)
- close && close(event)
- onClose && onClose(event)
- },
- [close, onClose, closeable]
- )
+ const handleClickIcon = useCallback(
+ (event: ITouchEvent) => {
+ event.stopPropagation()
+ if (closeable) {
+ setShowNoticeBar(false)
+ close?.(event)
+ onClose?.(event)
+ } else {
+ // 不可关闭时,将点击行为上抛,保持语义一致
+ click?.(event)
+ onClick?.(event)
+ }
+ },
+ [closeable, close, onClose, click, onClick]
+ )Also applies to: 485-499
🤖 Prompt for AI Agents
In src/packages/noticebar/noticebar.taro.tsx around lines 219-227 (also applies
to 485-499), the right-icon click handler unconditionally toggles visibility and
calls close/onClose even when closeable is false, causing non-closeable bars to
be forced visible and firing onClose incorrectly; update the handler so that if
closeable is true it sets show state to false and calls close/onClose, otherwise
if a custom rightIcon exists it should stop propagation only and invoke the
generic click/onClick handler (or let the event bubble) without changing
visibility or calling close/onClose; ensure dependency array remains correct and
mirror the same fix at the other occurrence (lines 485-499).
| | minHeight | 设置最小高度 | `string` | `26%` | | ||
| | left | 标题左侧部分 | `ReactNode` | `-` | | ||
| | title | 标题中间部分 | `ReactNode` | `-` | | ||
| | top | 頂部佔位 | `ReactNode` | `-` | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
文字使用不一致。
此处使用了繁体中文"頂部佔位",而同一属性在 src/packages/popup/doc.md 第 94 行使用的是简体中文"顶部占位"。为保持项目文档的一致性,建议统一使用简体中文。
应用以下修改以保持一致:
-| top | 頂部佔位 | `ReactNode` | `-` |
+| top | 顶部占位 | `ReactNode` | `-` |📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| | top | 頂部佔位 | `ReactNode` | `-` | | |
| | top | 顶部占位 | `ReactNode` | `-` | |
🤖 Prompt for AI Agents
In src/packages/popup/doc.taro.md around line 104, the property description uses
Traditional Chinese "頂部佔位" which is inconsistent with the Simplified Chinese
"顶部占位" used in src/packages/popup/doc.md line 94; update the string at line 104
to the Simplified Chinese "顶部占位" so both documents use the same wording.
| top, | ||
| description, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
新增 top API 与结构注入整体看起来合理
- API 扩展与渲染入口清晰;引入独立 ref 便于定位样式。
- 建议仅在 position==='bottom' 时渲染/定位
${classPrefix}-bottom-top,避免其它位置出现意外定位逻辑。 - 命名“top”与 CSS 属性同名,易产生理解歧义;若后续还有 header/extra 等区域,考虑顶层 API 命名一致性(可选)。
是否已同步更新类型定义与文档示例(多端)?若需要,我可批量检查类型与文档引用处。
Also applies to: 92-92, 192-200, 310-310
🏁 Script executed:
#!/bin/bash
# 检查类型与文档是否一致暴露了 top
rg -nP --type=ts,tsx '\btop\?\s*:\s*ReactNode' src/types -C2
rg -nP 'Popup.*top' src/packages/popup -C2
rg -nP 'top.*Popup' src/packages/popup/doc.* -C2Length of output: 458
Now let me run scripts to directly inspect the codebase:
🏁 Script executed:
#!/bin/bash
# Directly inspect popup.tsx file at mentioned line numbers and surrounding code
# Also search for type definitions
# 1. Check lines 69-70 in popup.tsx
echo "=== Lines 69-70 in popup.tsx ==="
sed -n '65,75p' src/packages/popup/popup.tsx
# 2. Check line 92 in popup.tsx
echo -e "\n=== Line 92 in popup.tsx ==="
sed -n '88,96p' src/packages/popup/popup.tsx
# 3. Check lines 192-200 in popup.tsx
echo -e "\n=== Lines 192-200 in popup.tsx ==="
sed -n '188,204p' src/packages/popup/popup.tsx
# 4. Check line 310 in popup.tsx
echo -e "\n=== Line 310 in popup.tsx ==="
sed -n '306,314p' src/packages/popup/popup.tsx
# 5. Find type definition files
echo -e "\n=== Type definition files for Popup ==="
find src -name "*.d.ts" -o -name "*type*" | grep -i popup | head -10
# 6. Search for interface or type definitions with 'top'
echo -e "\n=== Type definitions with 'top' property ==="
rg -n "^\s*top\?" src/packages/popup --type ts --type tsx -C 2 2>/dev/null || echo "No matches found"
# 7. Find documentation files
echo -e "\n=== Documentation files ==="
find src/packages/popup -name "*.md" -o -name "*doc*" | head -10Length of output: 1513
🏁 Script executed:
#!/bin/bash
# Find type definitions and understand the structure
# 1. Search for PopupProps interface/type definition
echo "=== PopupProps type definition ==="
rg -n "interface PopupProps|type PopupProps|export.*Props" src/packages/popup/popup.tsx -A 50 | head -80
# 2. Check the index.ts file for exports
echo -e "\n=== Index.ts exports ==="
cat src/packages/popup/index.ts 2>/dev/null || echo "File not found"
# 3. Search for 'top' property in type definitions
echo -e "\n=== Search for 'top' in all tsx/ts files ==="
rg -n '\btop\b' src/packages/popup/popup.tsx -B 2 -A 2 | grep -E "(interface|type|:\s|top)" | head -20
# 4. Check CSS files for bottom-top class
echo -e "\n=== Search for CSS class 'bottom-top' ==="
find src/packages/popup -name "*.css" -o -name "*.scss" -o -name "*.less" | xargs rg -n "bottom-top" 2>/dev/null || echo "No CSS files found"
# 5. Check documentation for 'top' prop examples
echo -e "\n=== Check documentation for top prop ==="
rg -n "top" src/packages/popup/doc.md -B 2 -A 2 | head -40
# 6. Look at full popup.tsx top-level interface
echo -e "\n=== Full props destructuring area ==="
sed -n '1,100p' src/packages/popup/popup.tsx | tail -50Length of output: 2550
🏁 Script executed:
#!/bin/bash
# Find type definitions and verify consistency
# 1. Find the types file
echo "=== Find @/types location ==="
find src -name "types.ts" -o -path "*/types/index.ts" | head -5
# 2. Search for TaroPopupProps definition
echo -e "\n=== Search for TaroPopupProps definition ==="
rg -n "TaroPopupProps|interface.*PopupProps" src -A 30 | head -100
# 3. Check if 'top' property exists in type
echo -e "\n=== Check for 'top' property in Popup types ==="
rg -n "top.*ReactNode|top\?" src -C 3 | grep -A 5 -B 5 "Popup\|Props" | head -40
# 4. Search for where "bottom-top" class is used/styled
echo -e "\n=== Search for bottom-top class usage ==="
rg -n "bottom-top" src -C 2
# 5. Search for position check in renderTop or similar
echo -e "\n=== Check position logic in popup ==="
sed -n '190,210p' src/packages/popup/popup.tsx
# 6. Check test file for top prop usage
echo -e "\n=== Check test file for top prop ==="
rg -n "top" src/packages/popup/__tests__/popup.spec.tsx -B 2 -A 2Length of output: 7005
🏁 Script executed:
#!/bin/bash
# Find BasePopup and verify type definitions
# 1. Search for BasePopup definition
echo "=== Search for BasePopup definition ==="
rg -n "interface BasePopup|type BasePopup|export.*BasePopup" src -A 40 | head -120
# 2. Directly search for 'top' in popup type files
echo -e "\n=== Search for 'top' in popup type files ==="
rg -n "top" src/types/spec/popup/ -B 3 -A 3
# 3. Check if class naming "bottom-top" appears elsewhere
echo -e "\n=== Check class naming patterns ==="
rg -n "popup-.*-top|bottom-top" src --type ts --type tsx | head -20
# 4. Verify test expectation
echo -e "\n=== Full test context ==="
sed -n '35,40p' src/packages/popup/__tests__/popup.spec.tsxLength of output: 3158
修复类名与条件渲染逻辑,确保与测试和设计一致
在 src/packages/popup/popup.tsx 中发现以下问题:
-
第 195 行类名错误:当前生成
${classPrefix}-bottom-top,但测试期望${classPrefix}-top(.nut-popup-top)。类名不匹配导致测试失败。 -
第 192-200 行缺少位置条件:
renderTop()无条件渲染,而renderTitle()函数(第 203 行)采用position === 'bottom'检查。建议renderTop()也遵循相同的位置逻辑模式,避免不一致行为。
验证结果:
- ✓ 类型定义已正确包含
top?: ReactNode(src/types/spec/popup/base.ts:20) - ✓ 文档已更新(
doc.md第 94 行) - ✗ 实现存在类名与条件逻辑缺陷
🤖 Prompt for AI Agents
In src/packages/popup/popup.tsx around lines 192-203 (and specifically line
~195), fix the rendering and class name logic: change the generated class from
`${classPrefix}-bottom-top` to `${classPrefix}-top` and make renderTop() follow
the same positional guard as renderTitle() by only rendering when position ===
'top'; ensure renderTop uses the correct classPrefix (`${classPrefix}-top`) and
conditional check to match tests and design.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这里可以看下ai提示~
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check the test file to see what class name is expected
echo "=== Test file content for top prop ==="
cat src/packages/popup/__tests__/popup.spec.tsx | grep -A 10 -B 10 "nut-popup-top" || echo "No match found in test file"
# Check SCSS to see the class structure
echo -e "\n=== SCSS class structure ==="
cat src/packages/popup/popup.scss | grep -A 5 -B 2 "bottom-top\|&-top"
# Check demo6 to see how top prop is used
echo -e "\n=== Demo6 usage ==="
cat src/packages/popup/demos/taro/demo6.tsx | grep -A 20 "visible2"
# Check if there are other position checks in renderTitle
echo -e "\n=== renderTitle position logic ==="
sed -n '202,230p' src/packages/popup/popup.tsx
Length of output: 2842
@xiaoyatong 我检查了一下,AI 提示中关于类名的问题是误判,但位置条件判断的建议是合理的:
1. 类名问题 - AI 误判 ❌
AI 把两个不同的功能混淆了:
- 现有功能:
position="top"→ 生成.nut-popup-top类(用于从顶部弹出) - 新增功能:
topprop → 生成.nut-popup-bottom-top类(在 bottom 弹窗标题上方显示内容)
当前实现 ${classPrefix}-bottom-top 与 SCSS 定义 &-top (嵌套在 &-bottom 下) 是完全匹配的,无需修改。
2. 位置条件判断 - 建议合理 ✅
不过 AI 关于位置判断的建议是对的。建议在 renderTop() 中添加位置检查:
const renderTop = () => {
if (!top || position !== 'bottom') return null
return (
<div className={`${classPrefix}-bottom-top`} ref={topNodeRef}>
{top}
</div>
)
}理由:
- 文档说明该功能是"在 title 上侧展示用户自定义内容",主要针对 bottom 弹窗场景
- SCSS 类明确定义在
.nut-popup-bottom下 - 与
renderTitle()中left/title/description的条件渲染逻辑保持一致(第 206 行) - 在 center/top/left/right 位置渲染该元素没有实际意义
是否需要添加这个位置判断?
| useEffect(() => { | ||
| if (topNodeRef.current && nodeRef.current) { | ||
| topNodeRef.current.style.bottom = `${nodeRef.current?.clientHeight}px` | ||
| } | ||
| }, [innerVisible]) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
resizable 场景下“顶部区块”不会跟随高度变化,易出现错位
仅在 innerVisible 变化时设置一次 bottom,会在拖拽调整高度或内容高度变化后与弹层脱节。建议:
- 仅在 position==='bottom' 时更新;
- 在拖拽过程中同步 topNodeRef 的 bottom;
- 可选:用 ResizeObserver 监听高度变化,避免手动同步多处。
修复示例(必要最少变更):
- useEffect(() => {
- if (topNodeRef.current && nodeRef.current) {
- topNodeRef.current.style.bottom = `${nodeRef.current?.clientHeight}px`
- }
- }, [innerVisible])
+ useEffect(() => {
+ if (position === 'bottom' && topNodeRef.current && nodeRef.current) {
+ topNodeRef.current.style.bottom = `${nodeRef.current.clientHeight}px`
+ }
+ }, [innerVisible, position])并在拖拽时同步:
nodeRef.current.style.height = `${currentHeight}px`
+ // 同步顶部区块位置(仅 bottom 模式)
+ if (position === 'bottom' && topNodeRef.current) {
+ topNodeRef.current.style.bottom = `${currentHeight}px`
+ }Also applies to: 264-272
🤖 Prompt for AI Agents
In src/packages/popup/popup.tsx around lines 147-152, the current useEffect only
updates topNodeRef.style.bottom once when innerVisible changes, causing the top
block to desync during resizes or dragging; change the logic to only run when
position === 'bottom', and add a ResizeObserver on nodeRef (or listen to its
size changes) to update topNodeRef.style.bottom to
`${nodeRef.current.clientHeight}px` whenever height changes; additionally,
invoke the same update function from the drag handlers so the bottom is synced
during dragging; apply the identical fix to the similar section at lines
264-272.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个看上去很有用~~
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@xiaoyatong 很高兴这个建议对您有帮助!😊
如果您在实现修复时需要任何帮助,或者想讨论其他实现方案(比如使用 ResizeObserver),随时告诉我。
| /* #ifndef dynamic*/ | ||
| display: inline-flex; | ||
| /* #endif */ | ||
| /* #ifdef dynamic*/ | ||
| display: flex; | ||
| /* #endif */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
CSS 级联会覆盖条件注释 — 无法按预期工作。
在第 124-129 行添加的预处理器风格的注释(/* #ifndef dynamic*/ 和 /* #ifdef dynamic*/)不会被 SCSS 编译器解析。SCSS 会编译两个 display 规则,CSS 级联机制会始终应用最后定义的值(display: flex;),使条件逻辑无效。
条件注释只有在存在专门的自定义预处理器来处理这些指令时才能生效。当前的实现方式:
- 不符合 SCSS/CSS 标准
- 会导致
display: inline-flex;被忽略 - 行为无法根据
dynamic状态改变
请验证以下几点:
- 构建管道中是否存在处理
/* #ifndef */和/* #ifdef */指令的自定义预处理器? - 预期的行为是什么?是否应该根据
dynamic条件动态改变display属性?
如果确实需要条件分支,建议改用以下标准方案之一:
方案 1:使用 SCSS @if 和变量
&-left,
&-right {
@if variable-exists(dynamic) and $dynamic {
display: flex;
} @else {
display: inline-flex;
}
align-items: center;
// ...
}方案 2:使用 CSS 自定义属性(CSS Variables)
&-left,
&-right {
display: var(--searchbar-display, inline-flex);
align-items: center;
// ...
}然后在 JavaScript 或根样式中动态设置 --searchbar-display 的值。
🏁 Script executed:
#!/bin/bash
# Search for similar preprocessor-style directives in the codebase
echo "=== Searching for preprocessor directives ==="
rg -n '#ifndef|#ifdef|#endif' --type scss --type css --type ts --type js
echo ""
echo "=== Searching for 'dynamic' in searchbar files ==="
rg -n 'dynamic' src/packages/searchbar/ -C2
echo ""
echo "=== Checking for build config files ==="
fd -e 'webpack.config.*|vite.config.*|taro.config.*|rollup.config.*' .
echo ""
echo "=== Checking package.json for build tools ==="
cat package.json | grep -A 20 '"devDependencies"' | head -30
echo ""
echo "=== Looking at surrounding code context ==="
sed -n '110,135p' src/packages/searchbar/searchbar.scssLength of output: 1971
🏁 Script executed:
#!/bin/bash
# Search for taro config files at any depth
echo "=== Searching for taro.config files ==="
find . -name 'taro.config.*' -o -name '.tarorc*' 2>/dev/null
echo ""
echo "=== Checking searchbar component entry ==="
cat src/packages/searchbar/index.ts 2>/dev/null || cat src/packages/searchbar/index.tsx 2>/dev/null || cat src/packages/searchbar/index.js 2>/dev/null || echo "Not found"
echo ""
echo "=== Searching for preprocessor/dynamic references in ts/tsx files ==="
rg -n 'dynamic|preprocessor|#ifdef|#ifndef' --type ts --type tsx -i | head -20
echo ""
echo "=== Checking project root for config/docs ==="
ls -la | grep -i 'taro\|config\|readme'
echo ""
echo "=== Checking package.json main/type fields ==="
cat package.json | grep -E '"main"|"type"|"scripts"' | head -20Length of output: 1521
🏁 Script executed:
#!/bin/bash
# Check if "dynamic" mode is used anywhere in the codebase
echo "=== Searching for 'dynamic' across entire codebase ==="
rg -n -i 'dynamic.*display|display.*dynamic' --type-list | head -10
find . -type f \( -name '*.ts' -o -name '*.tsx' -o -name '*.js' -o -name '*.jsx' \) -exec grep -l 'dynamic' {} \; 2>/dev/null | head -10
echo ""
echo "=== Check searchbar component context - is there a dynamic mode parameter? ==="
cat src/packages/searchbar/searchbar.tsx 2>/dev/null | grep -A 5 -B 5 'interface\|type.*Props\|export.*SearchBar' | head -40
echo ""
echo "=== Check if NutUI docs mention dynamic or display modes ==="
cat README.md | grep -i 'dynamic\|display\|searchbar' | head -10
echo ""
echo "=== Verify: what does SCSS compilation produce with cascade rule? ==="
echo "Two consecutive display properties will result in the LAST one being used in final CSS"
</parameter>Length of output: 1561
CSS 级联覆盖条件注释——预处理器未激活,条件逻辑无效。
在第 124-129 行的预处理器风格注释(/* #ifndef dynamic*/ 和 /* #ifdef dynamic*/)无法生效,原因如下:
- 预处理器未启用:项目中不存在
taro.config.js,Taro 条件编译未激活 - SCSS 编译级联:SCSS 编译器将这些注释视为普通注释,编译两个
display规则,CSS 级联机制最终只应用最后定义的值(display: flex;) - 无效的条件分支:第 125 行的
display: inline-flex;被彻底忽略,dynamic变量在组件中不存在
验证结果表明:SearchBar 组件不存在 dynamic 模式或相关属性,这些指令是完全无效的代码。
需要修复:
- 移除这些无效的预处理器注释,保留单一的
display值;或 - 如果确实需要条件分支,使用 SCSS 变量、CSS 自定义属性或组件 props 实现
🤖 Prompt for AI Agents
In src/packages/searchbar/searchbar.scss lines 124-129, the preprocessor-style
comments (/* #ifndef dynamic*/ / /* #ifdef dynamic*/ ) are inert here and cause
both display rules to be emitted, so remove those conditional comments and keep
a single display declaration (e.g., keep display: flex; and delete display:
inline-flex; and the surrounding comment markers). If conditional behavior is
actually required, replace this with a real mechanism: use an SCSS variable or
CSS custom property toggled by a class or the component prop (set the class from
the component and switch display via that class) rather than preprocessor
comments.
| const setActionWidth = (fn: any) => { | ||
| const res = fn() | ||
| if (res.left !== undefined) { | ||
| updateState({ | ||
| ...actionWidth.current, | ||
| left: res.left, | ||
| }) | ||
| } | ||
|
|
||
| getWidth() | ||
| }, [leftId, rightId, setActionWidth]) | ||
|
|
||
| const wrapperStyle = { | ||
| transform: `translate(${state.offset}${!harmony() ? 'px' : ''}, 0)`, | ||
| transitionDuration: state.dragging ? '0s' : '.6s', | ||
| } | ||
| const onTouchStart = async (event: BaseEventOrig<HTMLDivElement>) => { | ||
| if (leftWrapper.current) { | ||
| const leftRect = await getRectInMultiPlatform(leftWrapper.current, leftId) | ||
| leftRect && setActionWidth((v: any) => ({ ...v, left: leftRect.width })) | ||
| if (res.right !== undefined) { | ||
| updateState({ | ||
| ...actionWidth.current, | ||
| right: res.right, | ||
| }) | ||
| } | ||
| if (rightWrapper.current) { | ||
| const rightRect = await getRectInMultiPlatform( | ||
| rightWrapper.current, | ||
| rightId | ||
| ) | ||
| rightRect && | ||
| setActionWidth((v: any) => ({ ...v, right: rightRect.width })) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
修复 setActionWidth 回调参数导致的运行时错误
当前对 fn() 不传参,getWidth 里回调使用了 { ...v },会对 undefined 执行对象展开,产生 TypeError。应将当前宽度作为参数传入回调,或直接合并更新。
建议最小修复:
- const setActionWidth = (fn: any) => {
- const res = fn()
+ const setActionWidth = (fn: any) => {
+ const res = fn(actionWidth.current)
if (res.left !== undefined) {
updateState({
...actionWidth.current,
left: res.left,
})
}
if (res.right !== undefined) {
updateState({
...actionWidth.current,
right: res.right,
})
}
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const setActionWidth = (fn: any) => { | |
| const res = fn() | |
| if (res.left !== undefined) { | |
| updateState({ | |
| ...actionWidth.current, | |
| left: res.left, | |
| }) | |
| } | |
| getWidth() | |
| }, [leftId, rightId, setActionWidth]) | |
| const wrapperStyle = { | |
| transform: `translate(${state.offset}${!harmony() ? 'px' : ''}, 0)`, | |
| transitionDuration: state.dragging ? '0s' : '.6s', | |
| } | |
| const onTouchStart = async (event: BaseEventOrig<HTMLDivElement>) => { | |
| if (leftWrapper.current) { | |
| const leftRect = await getRectInMultiPlatform(leftWrapper.current, leftId) | |
| leftRect && setActionWidth((v: any) => ({ ...v, left: leftRect.width })) | |
| if (res.right !== undefined) { | |
| updateState({ | |
| ...actionWidth.current, | |
| right: res.right, | |
| }) | |
| } | |
| if (rightWrapper.current) { | |
| const rightRect = await getRectInMultiPlatform( | |
| rightWrapper.current, | |
| rightId | |
| ) | |
| rightRect && | |
| setActionWidth((v: any) => ({ ...v, right: rightRect.width })) | |
| } | |
| const setActionWidth = (fn: any) => { | |
| const res = fn(actionWidth.current) | |
| if (res.left !== undefined) { | |
| updateState({ | |
| ...actionWidth.current, | |
| left: res.left, | |
| }) | |
| } | |
| if (res.right !== undefined) { | |
| updateState({ | |
| ...actionWidth.current, | |
| right: res.right, | |
| }) | |
| } | |
| } |
🤖 Prompt for AI Agents
In src/packages/swipe/swipe.taro.tsx around lines 84 to 98, setActionWidth calls
fn() with no args and then spreads returned values causing a TypeError when the
callback does something like `{ ...v }` with undefined; change setActionWidth to
pass the current width into the callback (e.g., call fn(actionWidth.current))
and update state by merging with existing values so undefined fields do not
overwrite current widths (use conditional/nullable merging so only provided
left/right replace existing ones).
| if (props.disabled) return | ||
| touch.move(event) | ||
| props.onTouchMove?.(event) | ||
| if (touch.isHorizontal()) { | ||
| lockClick.current = true | ||
| const newState = { ...state, dragging: true } | ||
| const isEdge = !opened || touch.deltaX.current * startOffset.current < 0 | ||
| if (isEdge) { | ||
| preventDefault(event, true) | ||
| } | ||
|
|
||
| newState.offset = rangeCalculation( | ||
| const offset = rangeCalculation( | ||
| touch.deltaX.current + startOffset.current, | ||
| -actionWidth.current.right || 0, | ||
| actionWidth.current.left || 0 | ||
| ) | ||
| setState(newState) | ||
| setState((prevState) => ({ | ||
| ...prevState, | ||
| dragging: true, | ||
| offset: Number(offset) || 0, | ||
| })) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
修正 opened 引用的误用,避免阈值判断失效
opened 是 ref,应使用 opened.current。否则 !opened 恒为 false,边缘判定与滚动阻止逻辑异常。
应用以下修复:
- const isEdge = !opened || touch.deltaX.current * startOffset.current < 0
+ const isEdge = !opened.current || touch.deltaX.current * startOffset.current < 0📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (props.disabled) return | |
| touch.move(event) | |
| props.onTouchMove?.(event) | |
| if (touch.isHorizontal()) { | |
| lockClick.current = true | |
| const newState = { ...state, dragging: true } | |
| const isEdge = !opened || touch.deltaX.current * startOffset.current < 0 | |
| if (isEdge) { | |
| preventDefault(event, true) | |
| } | |
| newState.offset = rangeCalculation( | |
| const offset = rangeCalculation( | |
| touch.deltaX.current + startOffset.current, | |
| -actionWidth.current.right || 0, | |
| actionWidth.current.left || 0 | |
| ) | |
| setState(newState) | |
| setState((prevState) => ({ | |
| ...prevState, | |
| dragging: true, | |
| offset: Number(offset) || 0, | |
| })) | |
| if (props.disabled) return | |
| touch.move(event) | |
| props.onTouchMove?.(event) | |
| if (touch.isHorizontal()) { | |
| lockClick.current = true | |
| const isEdge = !opened.current || touch.deltaX.current * startOffset.current < 0 | |
| if (isEdge) { | |
| preventDefault(event, true) | |
| } | |
| const offset = rangeCalculation( | |
| touch.deltaX.current + startOffset.current, | |
| -actionWidth.current.right || 0, | |
| actionWidth.current.left || 0 | |
| ) | |
| setState((prevState) => ({ | |
| ...prevState, | |
| dragging: true, | |
| offset: Number(offset) || 0, | |
| })) |
🤖 Prompt for AI Agents
In src/packages/swipe/swipe.taro.tsx around lines 116 to 134, the code uses the
ref variable opened directly (e.g. !opened) which is incorrect; replace usages
with opened.current so the edge detection reads something like !opened.current
|| touch.deltaX.current * startOffset.current < 0. Ensure you reference
opened.current (and handle it if possibly undefined) when computing isEdge and
any other places in this block where opened is used.
| {content && | ||
| (td() ? ( | ||
| <Text className={`${classPrefix}-text`}>{content}</Text> | ||
| ) : ( | ||
| <View className={`${classPrefix}-text`}>{content}</View> | ||
| ))} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
验证 content 属性的类型安全性
条件渲染逻辑在动态平台下使用 Text 组件包裹 content。请确认 content 属性的类型定义仅允许字符串或原始类型,而不包含复杂的 React 元素。如果 content 可以是 ReactNode,在 td() 返回 true 时使用 Text 组件可能导致运行时错误。
运行以下脚本验证 content 的类型定义:
🏁 Script executed:
#!/bin/bash
# 描述: 检查 TaroToastProps 中 content 属性的类型定义
# 查找 TaroToastProps 类型定义
ast-grep --pattern $'interface TaroToastProps {
$$$
content: $_
$$$
}'
# 如果是类型别名形式
ast-grep --pattern $'type TaroToastProps = {
$$$
content: $_
$$$
}'Length of output: 0
---
🏁 Script executed:
```shell
#!/bin/bash
# Search for TaroToastProps definition using ripgrep
rg -n "TaroToastProps" --type=ts --type=tsx -A 10
# Also search directly for content property definition in toast file
rg -n "content\s*:" src/packages/toast/toast.taro.tsx -A 2 -B 2
Length of output: 167
---
🏁 Script executed:
```shell
#!/bin/bash
# Search for TaroToastProps interface or type declaration
rg -n "interface TaroToastProps|type TaroToastProps" --type=ts -A 15
# Also search the file for content property with type annotation
rg -n "content\s*:\s*" src/packages/toast/toast.taro.tsx -B 5
# Check if there's a separate types file
fd -e ts -e js src/packages/toast | head -20
Length of output: 650
---
🏁 Script executed:
```shell
#!/bin/bash
# Find BaseToast type definition
rg -n "interface BaseToast|type BaseToast" --type=ts -A 30
# Also check what's exported from base toast types
rg -n "content" src/types/spec/toast -B 2 -A 2 --type=ts
Length of output: 1040
修复 content 在 Text 组件中的类型安全问题
已确认 content 属性的类型为 ReactNode(见 src/types/spec/toast/base.ts 第14行),但代码在 td() 返回 true 时将其包裹在 Taro Text 组件中。Text 组件仅支持文本/字符串内容,不能渲染复杂的 React 元素。当 content 为非字符串的 ReactNode 时,将导致运行时错误。
建议修复方案:
- 当
td()为 true 时,也使用View组件(与 else 分支一致),以支持任意 ReactNode 内容 - 或添加类型约束和运行时检查,确保
td()为 true 时content仅为字符串类型
🤖 Prompt for AI Agents
In src/packages/toast/toast.taro.tsx around lines 184 to 189, the code wraps the
ReactNode content in a Taro Text component when td() is true, but Text only
supports plain string/text and will throw at runtime for non-string ReactNodes;
change the branch so that when td() returns true you render a View (same as the
else branch) to support arbitrary ReactNode content, or alternatively add a
runtime/type guard to only use Text when typeof content === 'string' and fall
back to View otherwise.
src/packages/range/range.taro.tsx
Outdated
| useLayoutEffect(() => { | ||
| if (root.current) { | ||
| getRectInMultiPlatform(root.current).then((rect) => { | ||
| useReady(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
大佬,这里撤回到useReady的原因是什么?
useReady只会在页面第一次挂载的时候触发,如果当前组件是懒加载渲染的就不会重复触发了
比如页面渲染2秒后再渲染当前组件,就不会触发useReady,理论上就算使用了nextTick也不行。
最好还是使用react的hooks,跟组件绑定,不跟页面绑定
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这里可以集中测试一下多端的反应~~ h5、小程序 还有鸿蒙端,我记得当时小程序就不好使了~ 可以看下
Codecov Report❌ Patch coverage is
❌ Your patch check has failed because the patch coverage (62.50%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## feat_v3.x #3374 +/- ##
=============================================
- Coverage 88.15% 88.13% -0.03%
=============================================
Files 291 291
Lines 19212 19228 +16
Branches 2988 2992 +4
=============================================
+ Hits 16937 16947 +10
- Misses 2269 2275 +6
Partials 6 6 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
相关的组件,需要在 h5 和小程序端验证一下可用性~~~
| top, | ||
| description, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这里可以看下ai提示~
| useEffect(() => { | ||
| if (topNodeRef.current && nodeRef.current) { | ||
| topNodeRef.current.style.bottom = `${nodeRef.current?.clientHeight}px` | ||
| } | ||
| }, [innerVisible]) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个看上去很有用~~
src/packages/range/range.taro.tsx
Outdated
| useLayoutEffect(() => { | ||
| if (root.current) { | ||
| getRectInMultiPlatform(root.current).then((rect) => { | ||
| useReady(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这里可以集中测试一下多端的反应~~ h5、小程序 还有鸿蒙端,我记得当时小程序就不好使了~ 可以看下
| maxlength={maxLength} | ||
| placeholder={ | ||
| placeholder !== undefined ? placeholder : locale.placeholder | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个是新增的~~
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
不要删掉~~
src/utils/taro/get-rect-by-id.ts
Outdated
| @@ -1,8 +1,21 @@ | |||
| import Taro, { createSelectorQuery } from '@tarojs/taro' | |||
|
|
|||
| const ENV_TYPE = { | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
可以把这个提炼到一个 公共的 constant 中
| import { useEffect, useRef } from 'react' | ||
| import isEqual from 'react-fast-compare' | ||
| import { Events, getCurrentInstance } from '@tarojs/taro' | ||
| import { eventCenter, getCurrentInstance } from '@tarojs/taro' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
需要在 h5 和小程序端验证一下
Summary by CodeRabbit
发布说明
新功能
top属性,支持在标题上方显示自定义内容样式优化
重构
Bug 修复