diff --git a/packages/vant-use/src/index.ts b/packages/vant-use/src/index.ts index d5e5ea087..6dbd05d8a 100644 --- a/packages/vant-use/src/index.ts +++ b/packages/vant-use/src/index.ts @@ -9,4 +9,5 @@ export * from './useScrollParent'; export * from './useEventListener'; export * from './usePageVisibility'; export * from './useCustomFieldValue'; +export * from './useRaf'; export * from './onMountedOrActivated'; diff --git a/packages/vant-use/src/useRaf/index.ts b/packages/vant-use/src/useRaf/index.ts new file mode 100644 index 000000000..db697b247 --- /dev/null +++ b/packages/vant-use/src/useRaf/index.ts @@ -0,0 +1,41 @@ +import { inBrowser } from '..'; + +interface UseRafOptions { + interval?: number; + isLoop?: boolean; +} + +export function useRaf( + fn: FrameRequestCallback, + options?: UseRafOptions, +): () => void { + if (inBrowser) { + const { interval = 0, isLoop = false } = options || {}; + let start: number; + let isStopped = false; + let rafId: number; + + const stop = () => { + isStopped = true; + cancelAnimationFrame(rafId); + }; + const frameWrapper = (timestamp: number) => { + if (isStopped) return; + if (start === undefined) { + start = timestamp; + } else if (timestamp - start > interval) { + fn(timestamp); + start = timestamp; + if (!isLoop) { + stop(); + return; + } + } + rafId = requestAnimationFrame(frameWrapper); + }; + rafId = requestAnimationFrame(frameWrapper); + + return stop; + } + return () => {}; +} diff --git a/packages/vant/docs/markdown/use-raf.en-US.md b/packages/vant/docs/markdown/use-raf.en-US.md new file mode 100644 index 000000000..631cc0779 --- /dev/null +++ b/packages/vant/docs/markdown/use-raf.en-US.md @@ -0,0 +1,73 @@ +# useRaf + +### Intro + +Provide convenient call and cancellation of [requestAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame). + +## Usage + +### Basic Usage + +### Single call + +```js +import { useRaf } from '@vant/use'; + +export default { + setup() { + let count = 0; + // A single call will be automatically canceledRaf after the callback is executed. + useRaf(() => { + count++; + console.log(count); // It will only be executed once. + }); + }, +}; +``` + +### Unlimited calls + +```js +import { useRaf } from '@vant/use'; + +export default { + setup() { + // isLoop Turn on the cycle + let count = 0; + const cancelRaf = useRaf( + () => { + count++; + console.log(count); // Unlimited execution until it is cancelled. + if (count === 5) { + cancelRaf(); + } + }, + { + interval: 0, // control interval to call this function + isLoop: true, + }, + ); + }, +}; +``` + +## API + +### Type Declarations + +```ts +function useRaf( + callback: () => void, + options: { + interval?: number; + isLoop?: boolean; + }, +) {} +``` + +### Params + +| Name | Description | Type | Default | +| --- | --- | --- | --- | +| callback | Callback | _() => void_ | _() => void_ | +| options | Options | _{ interval?: number; isLoop?: boolean }_ | _{ interval: 0; isLoop: false }_ | diff --git a/packages/vant/docs/markdown/use-raf.zh-CN.md b/packages/vant/docs/markdown/use-raf.zh-CN.md new file mode 100644 index 000000000..4d6eea746 --- /dev/null +++ b/packages/vant/docs/markdown/use-raf.zh-CN.md @@ -0,0 +1,73 @@ +# useRaf + +### 介绍 + +提供便捷的 [requestAnimationFrame](https://developer.mozilla.org/zh-CN/docs/Web/API/window/requestAnimationFrame) 的调用和取消。 + +## 代码演示 + +### 基本用法 + +### 单次调用 + +```js +import { useRaf } from '@vant/use'; + +export default { + setup() { + let count = 0; + // 单次调用在回调执行完后会被自动 cancelRaf + useRaf(() => { + count++; + console.log(count); // 只会执行 1 次 + }); + }, +}; +``` + +### 循环调用 + +```js +import { useRaf } from '@vant/use'; + +export default { + setup() { + // isLoop 开启循环 + let count = 0; + const cancelRaf = useRaf( + () => { + count++; + console.log(count); // 无限的执行,直到被 cancel + if (count === 5) { + cancelRaf(); + } + }, + { + interval: 0, // 控制间隔多久去调用 + isLoop: true, + }, + ); + }, +}; +``` + +## API + +### 类型定义 + +```ts +function useRaf( + callback: () => void, + options: { + interval?: number; + isLoop?: boolean; + }, +) {} +``` + +### 参数 + +| 参数 | 说明 | 类型 | 默认 | +| --- | --- | --- | --- | +| callback | 回调函数 | _() => void_ | _() => void_ | +| options | 配置参数 | _{ interval?: number; isLoop?: boolean }_ | _{ interval: 0; isLoop: false }_ | diff --git a/packages/vant/docs/markdown/vant-use-intro.en-US.md b/packages/vant/docs/markdown/vant-use-intro.en-US.md index 4046e113e..b1ca2acac 100644 --- a/packages/vant/docs/markdown/vant-use-intro.en-US.md +++ b/packages/vant/docs/markdown/vant-use-intro.en-US.md @@ -47,3 +47,4 @@ console.log(height.value); // -> window height | [useScrollParent](#/en-US/use-scroll-parent) | Get the closest parent element that is scrollable | | [useToggle](#/en-US/use-toggle) | Used to switch between `true` and `false` | | [useWindowSize](#/en-US/use-window-size) | Get the viewport width and height of the browser window | +| [useRaf](#/zh-CN/use-raf) | Used to manage the requestAnimationFrame | diff --git a/packages/vant/docs/markdown/vant-use-intro.zh-CN.md b/packages/vant/docs/markdown/vant-use-intro.zh-CN.md index dc4c63c0e..e5025b95d 100644 --- a/packages/vant/docs/markdown/vant-use-intro.zh-CN.md +++ b/packages/vant/docs/markdown/vant-use-intro.zh-CN.md @@ -51,3 +51,4 @@ console.log(height.value); // -> 窗口高度 | [useScrollParent](#/zh-CN/use-scroll-parent) | 获取元素最近的可滚动父元素 | | [useToggle](#/zh-CN/use-toggle) | 用于在布尔值之间进行切换 | | [useWindowSize](#/zh-CN/use-window-size) | 获取浏览器窗口的视口宽度和高度 | +| [useRaf](#/zh-CN/use-raf) | 提供requestAnimationFrame管理能力 | diff --git a/packages/vant/vant.config.mjs b/packages/vant/vant.config.mjs index 67421cd7c..e46d63997 100644 --- a/packages/vant/vant.config.mjs +++ b/packages/vant/vant.config.mjs @@ -503,6 +503,10 @@ location.href = location.href.replace('youzan.github.io', 'vant-ui.github.io'); path: 'use-window-size', title: 'useWindowSize', }, + { + path: 'use-raf', + title: 'useRaf', + }, ], }, ], @@ -967,6 +971,10 @@ location.href = location.href.replace('youzan.github.io', 'vant-ui.github.io'); path: 'use-window-size', title: 'useWindowSize', }, + { + path: 'use-raf', + title: 'useRaf', + }, ], }, ],