-
-
Notifications
You must be signed in to change notification settings - Fork 168
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
refactor: ♻️ 重构使用 requestAnimationFrame 的逻辑修复微信小程序报错方法重复定义的问题 #749
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
Walkthrough本次更改主要涉及对多个组件中 Changes
Assessment against linked issues
Possibly related PRs
Warning Rate limit exceeded@Moonofweisheng has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 5 minutes and 14 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
✅ Deploy Preview for wot-design-uni ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
Deploying wot-design-uni with Cloudflare Pages
|
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: 2
🧹 Outside diff range and nitpick comments (15)
src/uni_modules/wot-design-uni/components/wd-segmented/wd-segmented.vue (1)
68-71
: 建议保持动画标志的一致性异步实现看起来不错,但是在调用 updateActiveStyle 时移除了 animation 参数。建议明确设置动画标志,以保持行为的一致性和可预测性。
建议修改为:
onMounted(async () => { updateCurrentIndex() await pause() - updateActiveStyle(false) + updateActiveStyle(true) // 或者 false,取决于是否需要初始动画效果 })src/uni_modules/wot-design-uni/components/wd-index-bar/wd-index-bar.vue (1)
134-139
: 建议增加错误处理机制异步函数的改造方向正确,使用
pause
替代requestAnimationFrame
可以解决微信小程序的兼容性问题。不过建议添加 try-catch 来处理潜在的异步操作错误。建议按如下方式优化代码:
async function handleTouchEnd(e: TouchEvent) { const clientY = e.changedTouches[0].pageY state.activeIndex = getAnchorByPageY(clientY).index setScrollTop(getAnchorByPageY(clientY).$.exposed!.top.value - offsetTop) - await pause() - scrollState.touching = false + try { + await pause() + scrollState.touching = false + } catch (error) { + console.error('处理触摸结束事件时发生错误:', error) + scrollState.touching = false + } }src/uni_modules/wot-design-uni/components/wd-sticky/wd-sticky.vue (1)
111-117
: 异步处理优化建议函数重构后的实现逻辑清晰,但建议进行以下优化:
- 考虑添加错误处理机制
- 可以优化条件判断的顺序
建议按照以下方式重构:
async function handleResize(detail: any) { + if (!stickyBox || !stickyBox.observerForChild) return stickyState.width = detail.width stickyState.height = detail.height await pause() observerContentScroll() - if (!stickyBox || !stickyBox.observerForChild) return stickyBox.observerForChild(proxy) }这样可以:
- 提前进行条件检查,避免不必要的状态更新
- 减少执行路径,提高代码效率
src/uni_modules/wot-design-uni/components/wd-search/wd-search.vue (2)
106-109
: 建议添加错误处理机制虽然使用 async/await 简化了代码,但建议添加 try/catch 来处理潜在的异常情况。
建议修改为:
async function hackFocus(focus: boolean) { showInput.value = focus - await pause() + try { + await pause() + } catch (error) { + console.error('聚焦操作失败:', error) + } isFocused.value = focus }
112-116
: 建议优化延迟时间的处理方式当前代码中硬编码了 100ms 的延迟时间,建议将其提取为可配置的属性或添加注释说明原因。同时,建议添加 TypeScript 的返回值类型注解。
建议修改为:
-async function closeCover() { +async function closeCover(): Promise<void> { if (props.disabled) return - await pause(100) + // 等待 100ms 确保 DOM 更新完成 + await pause(props.coverDelay ?? 100) showPlaceHolder.value = false hackFocus(true) }src/uni_modules/wot-design-uni/components/wd-transition/wd-transition.vue (2)
Line range hint
165-174
: 建议完善错误处理逻辑当前的错误处理逻辑过于简单,建议进行以下改进:
} catch (error) { - /** - * - */ + console.error('离开动画执行失败:', error) + // 确保在发生错误时重置状态 + display.value = false + status.value = '' + enterPromise.value = null + leaveLifeCyclePromises.value = null }
Line range hint
1-215
: 架构建议:考虑提取过渡动画逻辑到独立的组合式函数为了提高代码的可维护性和复用性,建议将过渡动画的核心逻辑提取到一个独立的组合式函数(Composable)中。这样可以:
- 简化组件代码
- 方便其他组件复用相同的动画逻辑
- 便于单独测试动画逻辑
示例实现方向:
// useTransition.ts export function useTransition(options: TransitionOptions) { const status = ref<string>('') const display = ref<boolean>(false) // ... 其他状态和方法的实现 return { status, display, enter, leave, // ... 其他需要暴露的状态和方法 } }src/uni_modules/wot-design-uni/components/wd-textarea/wd-textarea.vue (2)
224-240
: 建议改进清除功能的实现当前实现存在以下可以改进的地方:
- 缺少错误处理机制
- 状态转换逻辑复杂且未文档化
- 可能存在竞态条件
建议按照以下方式重构:
-async function handleClear() { +/** + * 清除输入内容并管理焦点状态 + * @throws {Error} 当状态更新失败时抛出 + */ +async function handleClear() { + try { clearing.value = true focusing.value = false inputValue.value = '' if (props.focusWhenClear) { focused.value = false } await pause() if (props.focusWhenClear) { focused.value = true focusing.value = true } emit('change', { value: '' }) emit('update:modelValue', inputValue.value) emit('clear') + } catch (error) { + console.error('清除输入内容时发生错误:', error) + throw error + } finally { + if (!props.focusWhenClear) { + clearing.value = false + } + } }
Line range hint
241-252
: 建议优化失焦处理函数当前实现有以下几点可以优化:
- 硬编码的延迟时间(150ms)应该作为可配置项
- 缺少函数说明文档
- 事件参数类型不够明确
建议按照以下方式改进:
+interface BlurEvent { + cursor?: number; + value: string; +} + +/** + * 处理输入框失焦事件 + * @param detail 失焦事件详情 + */ -async function handleBlur({ detail }: any) { +async function handleBlur({ detail }: { detail: BlurEvent }) { + const CLEAR_DELAY = props.clearDelay ?? 150 // 新增配置项 // 等待150毫秒,clear执行完毕 - await pause(150) + await pause(CLEAR_DELAY) if (clearing.value) { clearing.value = false return } focusing.value = false emit('blur', { value: inputValue.value, - cursor: detail.cursor ? detail.cursor : null + cursor: detail.cursor ?? null }) }请考虑在组件的 props 中添加
clearDelay
配置项:clearDelay: { type: Number, default: 150 }src/uni_modules/wot-design-uni/components/wd-input/wd-input.vue (2)
233-249
: 建议添加错误处理机制异步函数的实现逻辑正确,但建议添加 try-catch 块来处理可能的异常情况,特别是在处理异步操作时。
建议按照以下方式重构:
async function handleClear() { + try { clearing.value = true focusing.value = false inputValue.value = '' if (props.focusWhenClear) { focused.value = false } await pause() if (props.focusWhenClear) { focused.value = true focusing.value = true } emit('change', { value: '' }) emit('update:modelValue', inputValue.value) emit('clear') + } catch (error) { + console.error('清除输入时发生错误:', error) + // 确保状态被重置 + clearing.value = false + focusing.value = false + } }
Line range hint
251-260
: 建议将延迟时间提取为可配置参数当前硬编码的 150ms 延迟时间应该提取为组件的可配置参数,这样可以根据不同场景调整延迟时间。
建议添加以下属性:
+ // 在 props 定义中添加 + clearDelay: { + type: Number, + default: 150, + description: '清除操作后的延迟时间(毫秒)' + } async function handleBlur() { - await pause(150) + await pause(props.clearDelay) if (clearing.value) { clearing.value = false return } focusing.value = false emit('blur', { value: inputValue.value }) }src/uni_modules/wot-design-uni/components/wd-calendar-view/monthPanel/month-panel.vue (1)
188-212
: 建议优化异步处理逻辑当前实现存在以下几点可以改进的地方:
- 函数中使用了两次
pause
,可能会导致不必要的延迟。建议合并这两次等待。- 缺少异步操作的错误处理机制。
建议按照以下方式优化代码:
async function scrollIntoView() { - // 等待渲染完毕 - await pause() + try { + // 等待渲染完毕 + await pause() + let activeDate: number | null = 0 if (isArray(props.value)) { activeDate = props.value![0] } else if (isNumber(props.value)) { activeDate = props.value } if (!activeDate) { activeDate = Date.now() } let top: number = 0 for (let index = 0; index < months.value.length; index++) { if (compareMonth(months.value[index].date, activeDate) === 0) { break } top += months.value[index] ? Number(months.value[index].height) : 0 } scrollTop.value = 0 - // 等待渲染完毕 - await pause() scrollTop.value = top + } catch (error) { + console.error('滚动到指定位置时发生错误:', error) + } }src/uni_modules/wot-design-uni/components/wd-select-picker/wd-select-picker.vue (1)
278-294
: 建议优化滚动位置计算逻辑当前的滚动位置计算逻辑比较复杂,建议考虑以下优化方案:
- Promise.all([getRect('.wd-select-picker__wrapper', false, proxy), getRect(wraperSelector, false, proxy), ...selectorPromise]).then((res) => { - if (isDef(res) && isArray(res)) { - const scrollView = res[0] - const wraper = res[1] - const target = res.slice(2) || [] - if (isDef(wraper) && isDef(scrollView)) { - const index = target.findIndex((item) => { - return item.bottom! > scrollView.top! && item.top! < scrollView.bottom! - }) - if (index < 0) { - scrollTop.value = -1 - nextTick(() => { - scrollTop.value = Math.max(0, target[0].top! - wraper.top! - scrollView.height! / 2) - }) - } - } - } - }) + const [scrollView, wrapper, ...targets] = await Promise.all([ + getRect('.wd-select-picker__wrapper', false, proxy), + getRect(wraperSelector, false, proxy), + ...selectorPromise + ]) + + if (!isDef(wrapper) || !isDef(scrollView) || targets.length === 0) return + + const isVisible = targets.some(item => + item.bottom! > scrollView.top! && item.top! < scrollView.bottom! + ) + + if (!isVisible) { + scrollTop.value = -1 + await nextTick() + scrollTop.value = Math.max(0, targets[0].top! - wrapper.top! - scrollView.height! / 2) + }src/uni_modules/wot-design-uni/components/wd-calendar/wd-calendar.vue (1)
Line range hint
316-328
: 异步处理逻辑优化合理将
open
方法改为异步方法并使用pause
替代requestAnimationFrame
是一个很好的改进:
- 通过使用
async/await
语法使代码更易读- 使用
pause
函数避免了与微信小程序的冲突- 保持了原有的渲染时序逻辑
建议在注释中补充暂停时间的说明。
建议添加更详细的注释:
- // 等待渲染完毕 + // 等待渲染完毕,默认暂停 16.7ms 模拟 requestAnimationFrame 的行为 await pause()src/uni_modules/wot-design-uni/components/common/util.ts (1)
Line range hint
446-452
: 实现正确,建议进一步优化
pause
函数的默认参数值设置合理,与标准的 30fps 刷新率相匹配。不过建议添加参数验证以确保传入的延迟时间为正数。建议添加参数验证:
export const pause = (ms: number = 1000 / 30) => { + if (ms <= 0) { + throw new Error('延迟时间必须大于 0') + } return new AbortablePromise((resolve) => { const timer = setTimeout(() => { clearTimeout(timer) resolve(true) }, ms) }) }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (13)
src/uni_modules/wot-design-uni/components/common/util.ts
(1 hunks)src/uni_modules/wot-design-uni/components/wd-calendar-view/monthPanel/month-panel.vue
(2 hunks)src/uni_modules/wot-design-uni/components/wd-calendar-view/yearPanel/year-panel.vue
(2 hunks)src/uni_modules/wot-design-uni/components/wd-calendar/wd-calendar.vue
(3 hunks)src/uni_modules/wot-design-uni/components/wd-collapse-item/wd-collapse-item.vue
(2 hunks)src/uni_modules/wot-design-uni/components/wd-index-bar/wd-index-bar.vue
(2 hunks)src/uni_modules/wot-design-uni/components/wd-input/wd-input.vue
(2 hunks)src/uni_modules/wot-design-uni/components/wd-search/wd-search.vue
(3 hunks)src/uni_modules/wot-design-uni/components/wd-segmented/wd-segmented.vue
(2 hunks)src/uni_modules/wot-design-uni/components/wd-select-picker/wd-select-picker.vue
(3 hunks)src/uni_modules/wot-design-uni/components/wd-sticky/wd-sticky.vue
(2 hunks)src/uni_modules/wot-design-uni/components/wd-textarea/wd-textarea.vue
(2 hunks)src/uni_modules/wot-design-uni/components/wd-transition/wd-transition.vue
(3 hunks)
🔇 Additional comments (26)
src/uni_modules/wot-design-uni/components/wd-calendar-view/yearPanel/year-panel.vue (2)
36-36
: 导入更改符合重构目标!
移除 requestAnimationFrame
并改用 pause
函数的更改直接解决了微信小程序中的冲突问题。
71-93
: 验证异步操作的兼容性
需要确保在各类小程序平台上 pause
函数的行为一致。
✅ Verification successful
Let me analyze the usage of pause()
function across the codebase to verify its behavior.
pause
函数的使用是安全且一致的
pause
函数是从 common/util
导入的公共工具函数,其实现是基于 Promise 的标准定时器封装,在各个组件中被广泛使用。在日历组件中使用两次 pause()
是为了确保 DOM 更新和滚动动画的平滑过渡,这是符合预期的实现方式。
- 函数定义位于
src/uni_modules/wot-design-uni/components/common/util.ts
,使用标准的 setTimeout 实现 - 在多个组件(Transition、Calendar、Input等)中都有类似的使用模式
- 实现采用了 AbortablePromise,具有可中断性,这提供了更好的性能控制
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 搜索其他组件中 pause 函数的使用方式
rg -A 3 "pause\(" src/uni_modules/wot-design-uni/
Length of output: 10259
Script:
#!/bin/bash
# Search for pause function definition
ast-grep --pattern 'const pause = $_'
# Search for pause function imports
rg "import.*pause.*from"
Length of output: 2978
src/uni_modules/wot-design-uni/components/wd-segmented/wd-segmented.vue (2)
35-35
: 导入更改看起来不错!
从 common/util 导入 pause 函数来替代 requestAnimationFrame 是一个好的改进,这样可以避免在微信小程序中的命名冲突。
70-70
: 验证 pause 函数在各平台的兼容性
为确保组件在所有支持的平台上都能正常工作,建议验证 pause 函数的实现。
✅ Verification successful
Let's gather more information about the pause function implementation.
pause 函数实现已验证,可以安全使用
在 common/util.ts
中找到了 pause
函数的实现,它是一个基于 AbortablePromise
的通用工具函数,使用 setTimeout
实现延时功能。该实现具有以下特点:
- 使用 Promise 封装,支持异步操作
- 默认延时时间为 1000/30 毫秒(约33.3ms)
- 支持自定义延时时间
- 基于
AbortablePromise
实现,支持取消操作
该实现是跨平台兼容的,可以安全使用。
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 检查 pause 函数的实现和使用情况
# 查找 pause 函数的定义
ast-grep --pattern 'function pause($$$) { $$$'
# 检查其他组件是否也使用了 pause 函数
rg -l 'pause.*\(' src/uni_modules/wot-design-uni/components/
Length of output: 1530
Script:
#!/bin/bash
# 查找 pause 函数的具体实现
rg -A 5 'function pause' src/uni_modules/wot-design-uni/components/
# 检查 common/util.ts 中的实现,因为这可能是公共实现
cat src/uni_modules/wot-design-uni/components/common/util.ts
Length of output: 17793
src/uni_modules/wot-design-uni/components/wd-collapse-item/wd-collapse-item.vue (2)
35-35
: 导入更改符合重构目标!
使用 pause
替代 requestAnimationFrame
的改动与微信小程序的兼容性需求相符,这样可以避免方法重复定义的问题。
106-117
: 建议优化暂停时间设置
代码实现从结构上看是合理的,但有以下几点建议:
- 考虑为
pause()
设置一个合适的延迟时间参数,以确保动画效果的流畅性 - 建议验证这个时间延迟在不同机型上的表现
✅ Verification successful
Let me analyze the results and generate one more verification to check the pause implementation:
暂停时间设置已经合理,无需修改
经过验证,pause()
函数已经有默认的延迟时间设置(1000/30 毫秒),这个时间设置与组件的过渡动画(0.3秒)相匹配。这是一个合理的实现:
pause()
的默认延迟约33ms,足够用于状态更新的微小延迟- collapse-item 组件使用了 0.3s 的过渡动画,这个动画时长符合流畅的用户体验标准
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 检查其他组件中是否有类似的 pause 使用模式,以确保一致性
# 搜索其他使用 pause 的组件
rg "pause\(\)" "src/uni_modules/wot-design-uni/components" -A 2 -B 2
# 搜索可能的动画相关配置
rg "transition|animation|duration" "src/uni_modules/wot-design-uni/components/wd-collapse"
Length of output: 10823
Script:
#!/bin/bash
# 检查 pause 函数的具体实现
rg "function pause" "src/uni_modules/wot-design-uni" -A 5 -B 2
# 检查组件中的动画相关配置
rg "transition-duration|animation-duration" "src/uni_modules/wot-design-uni/components/wd-collapse-item"
Length of output: 167
Script:
#!/bin/bash
# 搜索 pause 的定义,使用更广泛的模式
rg "pause\s*=|const pause" "src/uni_modules/wot-design-uni" -A 5 -B 2
# 检查 collapse-item 的样式文件中的过渡动画设置
rg "transition|animation" "src/uni_modules/wot-design-uni/components/wd-collapse-item/index.scss"
Length of output: 2359
src/uni_modules/wot-design-uni/components/wd-index-bar/wd-index-bar.vue (2)
30-30
: 导入更改符合重构目标!
将 requestAnimationFrame
替换为 pause
的更改与修复微信小程序兼容性问题的目标相符。
134-139
: 验证其他组件中的实现一致性
为确保整个代码库的一致性,需要验证其他组件是否也进行了类似的改造。
src/uni_modules/wot-design-uni/components/wd-sticky/wd-sticky.vue (2)
27-27
: 导入语句更新符合重构目标
导入语句的修改与PR的目标一致,通过引入 pause
函数来替代 requestAnimationFrame
,这有助于解决微信小程序中的冲突问题。
111-117
: 验证重构后的功能完整性
需要验证重构后的代码是否完全解决了问题 #549 中提到的冲突问题。
✅ Verification successful
Let me gather more information about the implementation of requestAnimationFrame
and its usage.
重构已完全解决 requestAnimationFrame 冲突问题
代码验证显示当前的实现已经完全解决了问题 #549 中提到的冲突:
- 原有的
requestAnimationFrame
已被封装在useRaf
composable 中,并且针对 H5 和非 H5 环境做了适配 - 在
util.ts
中的实现使用了AbortablePromise
和setInterval
替代,避免了全局命名冲突 wd-sticky
组件中移除了直接使用requestAnimationFrame
,改用pause()
函数处理异步操作
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 搜索是否还有其他地方使用了 requestAnimationFrame
rg "requestAnimationFrame"
# 检查是否有其他组件也需要类似的重构
ast-grep --pattern 'function $FUNC($_) {
$$$
requestAnimationFrame
$$$
}'
Length of output: 342
Script:
#!/bin/bash
# Check the implementation of requestAnimationFrame in util.ts
cat src/uni_modules/wot-design-uni/components/common/util.ts | grep -A 10 "requestAnimationFrame"
# Check the implementation in useRaf.ts
cat src/uni_modules/wot-design-uni/components/composables/useRaf.ts
# Check issue #549
gh issue view 549
Length of output: 1780
src/uni_modules/wot-design-uni/components/wd-search/wd-search.vue (2)
52-52
: 导入更改符合重构目标!
使用 pause
工具函数替代 requestAnimationFrame
是一个很好的选择,这样可以避免在微信小程序中的命名冲突问题。
Line range hint 1-150
: 验证组件在微信小程序中的兼容性
请确保所有 requestAnimationFrame
的使用都已替换为 pause
,并在微信小程序环境中完整测试组件的行为。
✅ Verification successful
requestAnimationFrame 已完全适配小程序环境
代码检查结果显示:
util.ts
中的requestAnimationFrame
已经被重写为使用setInterval
实现useRaf.ts
中已经对 H5 和非 H5 环境做了区分处理- 当前组件
wd-search
中使用的是pause
函数,符合小程序环境要求
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 检查是否还有其他文件使用了 requestAnimationFrame
echo "检查项目中是否还存在 requestAnimationFrame 的使用..."
rg -l "requestAnimationFrame" src/uni_modules/wot-design-uni/
# 检查是否有其他相关组件也需要类似修改
echo "检查其他可能需要类似修改的组件..."
rg -l "function\s+hackFocus|function\s+closeCover" src/uni_modules/wot-design-uni/components/
Length of output: 646
Script:
#!/bin/bash
# 检查 useRaf.ts 中的 requestAnimationFrame 使用情况
echo "检查 useRaf.ts 中的实现..."
rg -A 10 "requestAnimationFrame" src/uni_modules/wot-design-uni/components/composables/useRaf.ts
# 检查 util.ts 中的 requestAnimationFrame 使用情况
echo "检查 util.ts 中的实现..."
rg -A 10 "requestAnimationFrame" src/uni_modules/wot-design-uni/components/common/util.ts
# 检查是否有其他组件引用了 useRaf
echo "检查其他组件对 useRaf 的使用..."
rg -l "useRaf" src/uni_modules/wot-design-uni/components/
Length of output: 1140
src/uni_modules/wot-design-uni/components/wd-transition/wd-transition.vue (2)
20-20
: 导入更改看起来没有问题!
从 common/util 中导入 pause 函数的更改符合重构目标。
130-139
: 建议验证过渡动画的时序是否正确
使用 pause()
替代 requestAnimationFrame
的改动可能会影响动画的执行时序。建议进行以下验证:
- 确保动画的开始、执行和结束时机符合预期
- 验证在不同机型上的性能表现
✅ Verification successful
过渡动画时序实现已验证完成,无需担心
经过验证,pause()
函数替代 requestAnimationFrame
的改动是安全的:
pause()
函数实现了与原requestAnimationFrame
相同的帧率(30fps)- 动画时序控制逻辑保持不变,仍然通过 Promise 链式调用确保动画状态的正确过渡
- 新实现更加统一和可控,避免了跨平台差异
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 搜索其他使用 requestAnimationFrame 的地方,确保全部替换完成
rg "requestAnimationFrame"
Length of output: 260
Script:
#!/bin/bash
# 检查 util.ts 中 requestAnimationFrame 的实现
cat src/uni_modules/wot-design-uni/components/common/util.ts | grep -A 10 "requestAnimationFrame"
# 检查 useRaf.ts 中的使用情况
cat src/uni_modules/wot-design-uni/components/composables/useRaf.ts
Length of output: 1231
Script:
#!/bin/bash
# 检查 pause() 函数的实现
ast-grep --pattern 'const pause = $$$'
# 检查 wd-transition 组件中其他相关实现
cat src/uni_modules/wot-design-uni/components/wd-transition/wd-transition.vue
Length of output: 7200
src/uni_modules/wot-design-uni/components/wd-textarea/wd-textarea.vue (2)
77-77
: 导入更改符合重构目标!
移除 requestAnimationFrame
并改用 pause
工具函数的更改与重构目标一致,这样可以避免在微信小程序中的命名冲突问题。
Line range hint 224-252
: 验证重构更改的影响范围
需要确保移除 requestAnimationFrame
的更改不会影响其他组件的功能。
✅ Verification successful
Let me analyze the results. I can see that requestAnimationFrame
is only used in two utility files:
components/common/util.ts
- defines the utility functioncomponents/composables/useRaf.ts
- uses the utility function
Let me check if these utilities are used by other components and if the textarea component uses them.
移除 requestAnimationFrame 的更改是安全的
分析结果表明:
pause
函数是从common/util
导入的通用工具函数,而不是直接使用requestAnimationFrame
useRaf
组合式函数仅被wd-fab
组件和useCountDown
组合式 API 使用wd-textarea
组件只使用了pause
工具函数,且该函数在其他多个组件中也有使用
因此,移除 requestAnimationFrame
的更改不会影响其他组件的功能,重构是安全的。
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 描述:检查其他组件是否依赖 requestAnimationFrame
# 搜索所有可能使用 requestAnimationFrame 的地方
echo "检查 requestAnimationFrame 的使用情况..."
rg "requestAnimationFrame" src/uni_modules/wot-design-uni/
# 搜索可能受影响的相关组件
echo "检查相关组件..."
rg "wd-textarea" src/uni_modules/wot-design-uni/
Length of output: 4819
Script:
#!/bin/bash
# 检查 util.ts 和 useRaf.ts 的使用情况
echo "检查 util.ts 的引用..."
rg "from.*common/util" src/uni_modules/wot-design-uni/
echo "检查 useRaf.ts 的引用..."
rg "from.*useRaf" src/uni_modules/wot-design-uni/
# 检查 textarea 组件中是否使用这些工具
echo "检查 textarea 组件中的引用..."
rg "requestAnimationFrame|useRaf|pause" src/uni_modules/wot-design-uni/components/wd-textarea/
Length of output: 12441
src/uni_modules/wot-design-uni/components/wd-input/wd-input.vue (2)
90-90
: 导入更改符合重构目标!
移除 requestAnimationFrame
并改用 pause
工具函数的更改符合重构目标,有助于解决微信小程序中的冲突问题。
Line range hint 233-260
: 建议在微信小程序环境中验证修改
代码修改符合重构目标,建议在微信小程序环境中进行以下验证:
- 确认输入框的清除功能正常工作
- 验证与其他组件不再产生冲突
- 测试不同网络条件下的性能表现
✅ Verification successful
代码修改已经过充分验证,建议在微信小程序环境中进行测试
基于代码分析结果,我们可以确认:
pause
函数已经完全替代了requestAnimationFrame
,实现了统一的延迟处理机制- 在
wd-input
组件中的使用场景是合理的,用于处理清除和失焦的时序问题 - 其他组件(如
wd-transition
)也采用了相同的实现方式,说明这是一个经过验证的解决方案
建议测试要点:
- 清除输入框内容时的交互流畅性
- 清除后自动获焦的准确性
- 在不同网络条件下的表现
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 检查是否还有其他组件使用了 requestAnimationFrame
rg -l "requestAnimationFrame" src/uni_modules/wot-design-uni/components/
# 检查是否有其他组件使用了类似的延迟处理逻辑
ast-grep --pattern 'await pause($$$)'
Length of output: 233
Script:
#!/bin/bash
# 检查 util.ts 中的 requestAnimationFrame 使用情况
cat src/uni_modules/wot-design-uni/components/common/util.ts
# 检查 useRaf.ts 中的实现
cat src/uni_modules/wot-design-uni/components/composables/useRaf.ts
# 查找其他使用 pause 的组件
rg -l "pause\(" src/uni_modules/wot-design-uni/components/
Length of output: 19779
Script:
#!/bin/bash
# 检查其他组件中 pause 的具体使用场景
rg -C 3 "pause\(" src/uni_modules/wot-design-uni/components/wd-input/wd-input.vue
rg -C 3 "pause\(" src/uni_modules/wot-design-uni/components/wd-transition/wd-transition.vue
# 检查是否有其他组件使用了类似的清除和失焦逻辑
ast-grep --pattern 'async function handleClear() {
$$$
emit("clear")
$$$
}'
Length of output: 1582
src/uni_modules/wot-design-uni/components/wd-calendar-view/monthPanel/month-panel.vue (2)
66-66
: 导入语句修改正确!
成功替换了 requestAnimationFrame
为 pause
函数,这与修复微信小程序兼容性问题的目标相符。
188-212
: 验证 requestAnimationFrame 的完全移除
为确保完全解决微信小程序的兼容性问题,需要验证是否还有其他地方使用了 requestAnimationFrame
。
✅ Verification successful
requestAnimationFrame 已经得到适当处理
useRaf
组件已经正确处理了微信小程序的兼容性问题:
- 在 H5 环境下使用
requestAnimationFrame
- 在非 H5 环境(如微信小程序)下使用
setTimeout
模拟,频率为 30fps - 目前只在
wd-fab
和倒计时组件中使用,实现方式合理
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 搜索代码库中是否还存在 requestAnimationFrame 的使用
echo "检查是否还有 requestAnimationFrame 的使用..."
rg "requestAnimationFrame" --type vue --type ts --type js
echo "检查是否有其他组件使用了类似的动画帧逻辑..."
rg "requestAnim|animationFrame" --type vue --type ts --type js
Length of output: 537
Script:
#!/bin/bash
# 使用更通用的搜索方式查找相关代码
echo "检查是否还有 requestAnimationFrame 的使用..."
rg -t js -t jsx -t ts -t tsx -t vue "requestAnimationFrame"
echo "检查是否有其他组件使用了类似的动画帧逻辑..."
rg -t js -t jsx -t ts -t tsx -t vue "requestAnim|animationFrame"
# 使用 ast-grep 查找可能的动画相关函数调用
echo "使用 AST 分析查找动画相关代码..."
ast-grep --pattern 'requestAnimationFrame($_)'
Length of output: 763
Script:
#!/bin/bash
# 检查 useRaf.ts 文件的具体实现
echo "检查 useRaf.ts 的完整实现..."
cat src/uni_modules/wot-design-uni/components/composables/useRaf.ts
# 查找使用 useRaf 的地方
echo "查找使用 useRaf 的地方..."
rg "useRaf" -A 5 -B 5
Length of output: 5954
src/uni_modules/wot-design-uni/components/wd-select-picker/wd-select-picker.vue (3)
131-131
: 导入语句修改正确!
成功移除了 requestAnimationFrame
并添加了 pause
工具函数,这与修复微信小程序组件冲突的目标相符。
Line range hint 264-277
: 异步函数转换实现正确!
使用 async/await
和 pause
函数替换 requestAnimationFrame
的方案合理,可以有效解决微信小程序的方法重复定义问题。
Line range hint 264-294
: 建议验证其他组件是否需要类似修改
为确保整个项目的一致性,建议检查其他使用 requestAnimationFrame
的组件。
✅ Verification successful
Let me gather more information about the usage of similar scroll logic in other components.
根据检查结果,我可以生成最终响应了:
其他组件已经采用了合适的滚动实现方案
经过分析,其他使用滚动功能的组件(如 wd-index-bar、wd-calendar-view 等)都采用了类似的滚动实现方案:
- 使用
scrollTop
重置和设置新值的模式 - 通过
nextTick
确保视图更新 - 不依赖
requestAnimationFrame
当前的修改与其他组件保持一致,不需要在其他组件中进行类似修改。
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 搜索其他可能使用 requestAnimationFrame 的组件
echo "检查其他组件中的 requestAnimationFrame 使用情况..."
rg -l "requestAnimationFrame" "src/uni_modules/wot-design-uni/components"
# 检查是否有其他组件使用了类似的滚动逻辑
echo "检查类似滚动逻辑的使用..."
ast-grep --pattern 'scrollTop.value = -1'
Length of output: 484
Script:
#!/bin/bash
# 检查 util.ts 中的 requestAnimationFrame 相关代码
echo "检查 util.ts 中的 requestAnimationFrame 实现..."
cat "src/uni_modules/wot-design-uni/components/common/util.ts"
# 检查 useRaf.ts 中的实现
echo -e "\n检查 useRaf.ts 中的实现..."
cat "src/uni_modules/wot-design-uni/components/composables/useRaf.ts"
# 搜索其他可能使用类似滚动逻辑的组件
echo -e "\n检查其他组件中的滚动逻辑..."
rg -A 5 "scrollTop" "src/uni_modules/wot-design-uni/components"
Length of output: 34921
src/uni_modules/wot-design-uni/components/wd-calendar/wd-calendar.vue (2)
125-125
: 导入语句的修改符合重构目标
从工具函数中移除了 requestAnimationFrame
并添加了 pause
函数,这个改动与修复微信小程序中的冲突问题的目标相符。
Line range hint 316-328
: 验证其他组件是否需要类似修改
为确保修复的完整性,建议检查其他组件中是否存在类似的 requestAnimationFrame
使用场景。
✅ Verification successful
其他组件的 scrollIntoView 实现已经合理,无需类似修改
基于代码分析结果:
requestAnimationFrame
在组件库中已经有统一的封装实现,位于useRaf
和util.ts
中- 其他使用
scrollIntoView
的组件(如wd-tabs
和year-panel
)都已经正确处理了渲染时序:wd-tabs
使用了Promise.all
等待元素尺寸获取完成year-panel
已经使用await pause()
等待渲染完成
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 描述:检查代码库中其他可能使用 requestAnimationFrame 的地方
# 搜索所有包含 requestAnimationFrame 的文件
echo "查找包含 requestAnimationFrame 的文件:"
rg "requestAnimationFrame" --type vue --type ts --type js
# 搜索类似的渲染后滚动到视图的模式
echo "查找其他可能需要类似修复的滚动到视图的代码:"
rg "scrollIntoView" --type vue --type ts --type js
Length of output: 535
Script:
#!/bin/bash
# 使用更通用的搜索方式,不指定文件类型
echo "查找包含 requestAnimationFrame 的文件:"
rg "requestAnimationFrame"
echo -e "\n查找包含 scrollIntoView 的文件:"
rg "scrollIntoView"
Length of output: 3104
Script:
#!/bin/bash
# 检查 useRaf 的具体实现和使用情况
echo "检查 useRaf 的实现:"
cat src/uni_modules/wot-design-uni/components/composables/useRaf.ts
echo -e "\n检查 util.ts 中 requestAnimationFrame 的实现:"
cat src/uni_modules/wot-design-uni/components/common/util.ts | grep -A 10 "requestAnimationFrame"
echo -e "\n检查其他组件中的 scrollIntoView 实现:"
cat src/uni_modules/wot-design-uni/components/wd-tabs/wd-tabs.vue | grep -A 10 "scrollIntoView"
cat src/uni_modules/wot-design-uni/components/wd-calendar-view/yearPanel/year-panel.vue | grep -A 10 "scrollIntoView"
Length of output: 3009
src/uni_modules/wot-design-uni/components/common/util.ts (1)
Line range hint 435-443
: 建议移除 requestAnimationFrame 函数
根据 PR 目标,为了解决微信小程序中的冲突问题,建议完全移除 requestAnimationFrame
函数,统一使用 pause
函数来处理动画帧延迟。这样可以避免在微信小程序环境中出现方法重复定义的问题。
建议删除 requestAnimationFrame
函数,并将所有使用到该函数的地方替换为 pause
函数:
-export const requestAnimationFrame = (cb = () => {}) => {
- return new AbortablePromise((resolve) => {
- const timer = setInterval(() => {
- clearInterval(timer)
- resolve(true)
- cb()
- }, 1000 / 30)
- })
-}
Also applies to: 446-452
async function scrollIntoView() { | ||
await pause() | ||
let activeDate: number | null = null | ||
if (isArray(props.value)) { | ||
activeDate = props.value![0] | ||
} else if (isNumber(props.value)) { | ||
activeDate = props.value | ||
} | ||
|
||
if (!activeDate) { | ||
activeDate = Date.now() | ||
} | ||
if (!activeDate) { | ||
activeDate = Date.now() | ||
} | ||
|
||
let top: number = 0 | ||
for (let index = 0; index < years.value.length; index++) { | ||
if (compareYear(years.value[index].date, activeDate) === 0) { | ||
break | ||
} | ||
top += years.value[index] ? Number(years.value[index].height) : 0 | ||
let top: number = 0 | ||
for (let index = 0; index < years.value.length; index++) { | ||
if (compareYear(years.value[index].date, activeDate) === 0) { | ||
break | ||
} | ||
scrollTop.value = 0 | ||
requestAnimationFrame(() => { | ||
scrollTop.value = top | ||
}) | ||
}) | ||
top += years.value[index] ? Number(years.value[index].height) : 0 | ||
} | ||
scrollTop.value = 0 | ||
await pause() | ||
scrollTop.value = top |
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
建议优化异步滚动实现
当前实现存在以下几个问题:
- 使用了两次
pause()
,可能导致不必要的延迟 - 重置
scrollTop
为 0 后再设置实际值可能导致视觉跳动 - 缺少异步操作的错误处理
建议按照以下方式优化实现:
async function scrollIntoView() {
- await pause()
let activeDate: number | null = null
if (isArray(props.value)) {
activeDate = props.value![0]
} else if (isNumber(props.value)) {
activeDate = props.value
}
if (!activeDate) {
activeDate = Date.now()
}
let top: number = 0
for (let index = 0; index < years.value.length; index++) {
if (compareYear(years.value[index].date, activeDate) === 0) {
break
}
top += years.value[index] ? Number(years.value[index].height) : 0
}
- scrollTop.value = 0
- await pause()
+ try {
+ await pause()
+ scrollTop.value = top
+ } catch (error) {
+ console.error('滚动位置设置失败:', error)
+ }
- scrollTop.value = top
}
📝 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.
async function scrollIntoView() { | |
await pause() | |
let activeDate: number | null = null | |
if (isArray(props.value)) { | |
activeDate = props.value![0] | |
} else if (isNumber(props.value)) { | |
activeDate = props.value | |
} | |
if (!activeDate) { | |
activeDate = Date.now() | |
} | |
if (!activeDate) { | |
activeDate = Date.now() | |
} | |
let top: number = 0 | |
for (let index = 0; index < years.value.length; index++) { | |
if (compareYear(years.value[index].date, activeDate) === 0) { | |
break | |
} | |
top += years.value[index] ? Number(years.value[index].height) : 0 | |
let top: number = 0 | |
for (let index = 0; index < years.value.length; index++) { | |
if (compareYear(years.value[index].date, activeDate) === 0) { | |
break | |
} | |
scrollTop.value = 0 | |
requestAnimationFrame(() => { | |
scrollTop.value = top | |
}) | |
}) | |
top += years.value[index] ? Number(years.value[index].height) : 0 | |
} | |
scrollTop.value = 0 | |
await pause() | |
scrollTop.value = top | |
async function scrollIntoView() { | |
let activeDate: number | null = null | |
if (isArray(props.value)) { | |
activeDate = props.value![0] | |
} else if (isNumber(props.value)) { | |
activeDate = props.value | |
} | |
if (!activeDate) { | |
activeDate = Date.now() | |
} | |
let top: number = 0 | |
for (let index = 0; index < years.value.length; index++) { | |
if (compareYear(years.value[index].date, activeDate) === 0) { | |
break | |
} | |
top += years.value[index] ? Number(years.value[index].height) : 0 | |
} | |
try { | |
await pause() | |
scrollTop.value = top | |
} catch (error) { | |
console.error('滚动位置设置失败:', error) | |
} | |
} |
async function clearSearch() { | ||
str.value = '' | ||
clearing.value = true | ||
if (props.focusWhenClear) { | ||
isFocused.value = false | ||
} | ||
requestAnimationFrame() | ||
.then(() => requestAnimationFrame()) | ||
.then(() => requestAnimationFrame()) | ||
.then(() => { | ||
if (props.focusWhenClear) { | ||
showPlaceHolder.value = false | ||
hackFocus(true) | ||
} else { | ||
showPlaceHolder.value = true | ||
hackFocus(false) | ||
} | ||
emit('change', { | ||
value: '' | ||
}) | ||
emit('update:modelValue', '') | ||
emit('clear') | ||
}) | ||
await pause(100) | ||
if (props.focusWhenClear) { | ||
showPlaceHolder.value = false | ||
hackFocus(true) | ||
} else { | ||
showPlaceHolder.value = true | ||
hackFocus(false) | ||
} | ||
emit('change', { | ||
value: '' | ||
}) | ||
emit('update:modelValue', '') | ||
emit('clear') |
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
建议重构清空搜索的逻辑
当前的 clearSearch
函数职责过重,建议将其拆分为更小的函数以提高可维护性。同时,建议添加对 clearing 标志的使用说明。
建议重构为:
+/**
+ * 重置搜索框状态
+ */
+async function resetSearchState(shouldFocus: boolean): Promise<void> {
+ await pause(100)
+ showPlaceHolder.value = !shouldFocus
+ if (shouldFocus) {
+ hackFocus(true)
+ } else {
+ hackFocus(false)
+ }
+}
+/**
+ * 触发清空相关事件
+ */
+function emitClearEvents(): void {
+ emit('change', { value: '' })
+ emit('update:modelValue', '')
+ emit('clear')
+}
/**
+ * 清空搜索内容并重置状态
+ */
async function clearSearch(): Promise<void> {
str.value = ''
clearing.value = true
if (props.focusWhenClear) {
isFocused.value = false
}
- await pause(100)
- if (props.focusWhenClear) {
- showPlaceHolder.value = false
- hackFocus(true)
- } else {
- showPlaceHolder.value = true
- hackFocus(false)
- }
- emit('change', { value: '' })
- emit('update:modelValue', '')
- emit('clear')
+ await resetSearchState(props.focusWhenClear)
+ emitClearEvents()
}
📝 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.
async function clearSearch() { | |
str.value = '' | |
clearing.value = true | |
if (props.focusWhenClear) { | |
isFocused.value = false | |
} | |
requestAnimationFrame() | |
.then(() => requestAnimationFrame()) | |
.then(() => requestAnimationFrame()) | |
.then(() => { | |
if (props.focusWhenClear) { | |
showPlaceHolder.value = false | |
hackFocus(true) | |
} else { | |
showPlaceHolder.value = true | |
hackFocus(false) | |
} | |
emit('change', { | |
value: '' | |
}) | |
emit('update:modelValue', '') | |
emit('clear') | |
}) | |
await pause(100) | |
if (props.focusWhenClear) { | |
showPlaceHolder.value = false | |
hackFocus(true) | |
} else { | |
showPlaceHolder.value = true | |
hackFocus(false) | |
} | |
emit('change', { | |
value: '' | |
}) | |
emit('update:modelValue', '') | |
emit('clear') | |
/** | |
* 重置搜索框状态 | |
*/ | |
async function resetSearchState(shouldFocus: boolean): Promise<void> { | |
await pause(100) | |
showPlaceHolder.value = !shouldFocus | |
if (shouldFocus) { | |
hackFocus(true) | |
} else { | |
hackFocus(false) | |
} | |
} | |
/** | |
* 触发清空相关事件 | |
*/ | |
function emitClearEvents(): void { | |
emit('change', { value: '' }) | |
emit('update:modelValue', '') | |
emit('clear') | |
} | |
/** | |
* 清空搜索内容并重置状态 | |
*/ | |
async function clearSearch(): Promise<void> { | |
str.value = '' | |
clearing.value = true | |
if (props.focusWhenClear) { | |
isFocused.value = false | |
} | |
await resetSearchState(props.focusWhenClear) | |
emitClearEvents() | |
} |
✅ Closes: #549
🤔 这个 PR 的性质是?(至少选择一个)
🔗 相关 Issue
#549
💡 需求背景和解决方案
使用
pause
方法代替requestAnimationFrame
。☑️ 请求合并前的自查清单
Summary by CodeRabbit
新特性
wd-calendar
,wd-input
,wd-search
等)引入了异步处理,改善了用户交互的流畅性。pause
函数替代了requestAnimationFrame
,优化了组件的渲染和滚动行为。Bug 修复
文档
wd-search
组件的模板部分,提升了代码可读性。