From 098639bbb74cd9bee1126d2f83e16b39dd1dc002 Mon Sep 17 00:00:00 2001
From: webfansplz <308241863@qq.com>
Date: Sat, 25 Sep 2021 18:01:56 +0800
Subject: [PATCH] feat(watchOnce): new function (#765)
* feat(watchOnce): new Function
* chore(watchOnce): improve code
* chore: simplify
Co-authored-by: webfansplz <>
Co-authored-by: Anthony Fu
---
README.md | 2 +-
indexes.json | 7 +++++++
packages/functions.md | 1 +
packages/shared/index.ts | 1 +
packages/shared/watchOnce/index.md | 20 ++++++++++++++++++++
packages/shared/watchOnce/index.test.ts | 16 ++++++++++++++++
packages/shared/watchOnce/index.ts | 21 +++++++++++++++++++++
7 files changed, 67 insertions(+), 1 deletion(-)
create mode 100644 packages/shared/watchOnce/index.md
create mode 100644 packages/shared/watchOnce/index.test.ts
create mode 100644 packages/shared/watchOnce/index.ts
diff --git a/README.md b/README.md
index ab75d8a1d52c..5cbc847d745c 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ Collection of essential Vue Composition Utilities
-
+
diff --git a/indexes.json b/indexes.json
index 65c4031cb1f8..b459d6259ca5 100644
--- a/indexes.json
+++ b/indexes.json
@@ -422,6 +422,13 @@
"category": "Watch",
"description": "`watch` with the number of times triggered"
},
+ {
+ "name": "watchOnce",
+ "package": "shared",
+ "docs": "https://vueuse.org/shared/watchOnce/",
+ "category": "Watch",
+ "description": "`watch` with trigger once times"
+ },
{
"name": "watchWithFilter",
"package": "shared",
diff --git a/packages/functions.md b/packages/functions.md
index a33a860f7fb6..c928cfc69e2b 100644
--- a/packages/functions.md
+++ b/packages/functions.md
@@ -148,6 +148,7 @@
- [`throttledWatch`](https://vueuse.org/shared/throttledWatch/) — throttled watch
- [`until`](https://vueuse.org/shared/until/) — promised one-time watch for changes
- [`watchAtMost`](https://vueuse.org/shared/watchAtMost/) — `watch` with the number of times triggered
+ - [`watchOnce`](https://vueuse.org/shared/watchOnce/) — `watch` with trigger once times
- [`watchWithFilter`](https://vueuse.org/shared/watchWithFilter/) — `watch` with additional EventFilter control
- [`whenever`](https://vueuse.org/shared/whenever/) — shorthand for watching value to be truthy
diff --git a/packages/shared/index.ts b/packages/shared/index.ts
index 4367bf0d8777..21b9073c4768 100644
--- a/packages/shared/index.ts
+++ b/packages/shared/index.ts
@@ -40,5 +40,6 @@ export * from './useTimeoutFn'
export * from './useToggle'
export * from './utils'
export * from './watchAtMost'
+export * from './watchOnce'
export * from './watchWithFilter'
export * from './whenever'
diff --git a/packages/shared/watchOnce/index.md b/packages/shared/watchOnce/index.md
new file mode 100644
index 000000000000..6773408b5084
--- /dev/null
+++ b/packages/shared/watchOnce/index.md
@@ -0,0 +1,20 @@
+---
+category: Watch
+---
+
+# watchOnce
+
+`watch` that only triggers once.
+
+## Usage
+
+After the callback function has been triggered once, the watch will be stopped automatically.
+
+```ts
+import { watchOnce } from '@vueuse/core'
+
+watchOnce(source, () => {
+ // triggers only once
+ console.log('source changed!')
+})
+```
diff --git a/packages/shared/watchOnce/index.test.ts b/packages/shared/watchOnce/index.test.ts
new file mode 100644
index 000000000000..3a4efb16d7e1
--- /dev/null
+++ b/packages/shared/watchOnce/index.test.ts
@@ -0,0 +1,16 @@
+import { ref, nextTick } from 'vue-demi'
+import { watchOnce } from '.'
+
+describe('watchOnce', () => {
+ it('should work', async() => {
+ const num = ref(0)
+ const spy = jest.fn()
+
+ watchOnce(num, spy)
+ num.value = 1
+ await nextTick()
+ num.value = 2
+ await nextTick()
+ expect(spy).toBeCalledTimes(1)
+ })
+})
diff --git a/packages/shared/watchOnce/index.ts b/packages/shared/watchOnce/index.ts
new file mode 100644
index 000000000000..02cc38e1dfa8
--- /dev/null
+++ b/packages/shared/watchOnce/index.ts
@@ -0,0 +1,21 @@
+import { WatchSource, WatchCallback, WatchOptions, watch } from 'vue-demi'
+import { MapOldSources, MapSources } from '../utils'
+
+// overlads
+export function watchOnce[]>, Immediate extends Readonly = false>(source: T, cb: WatchCallback, MapOldSources>, options?: WatchOptions): void
+
+export function watchOnce[]>, Immediate extends Readonly = false>(source: T, cb: WatchCallback, MapOldSources>, options?: WatchOptions): void
+
+export function watchOnce = false>(sources: WatchSource, cb: WatchCallback, options?: WatchOptions): void
+
+// implementation
+export function watchOnce = false>(
+ source: any,
+ cb: any,
+ options?: WatchOptions,
+): void {
+ const stop = watch(source, (...args) => {
+ stop()
+ return cb(...args)
+ }, options)
+}