Skip to content

Commit

Permalink
feat(watchOnce): new function (vitest-dev#765)
Browse files Browse the repository at this point in the history
* feat(watchOnce): new Function

* chore(watchOnce): improve code

* chore: simplify

Co-authored-by: webfansplz <>
Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
  • Loading branch information
webfansplz and antfu committed Sep 25, 2021
1 parent 9f19c15 commit 098639b
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -7,7 +7,7 @@ Collection of essential Vue Composition Utilities
<a href="https://www.npmjs.com/package/@vueuse/core" target="__blank"><img src="https://img.shields.io/npm/v/@vueuse/core?color=a1b858&label=" alt="NPM version"></a>
<a href="https://www.npmjs.com/package/@vueuse/core" target="__blank"><img alt="NPM Downloads" src="https://img.shields.io/npm/dm/@vueuse/core?color=50a36f&label="></a>
<a href="https://vueuse.org" target="__blank"><img src="https://img.shields.io/static/v1?label=&message=docs%20%26%20demos&color=1e8a7a" alt="Docs & Demos"></a>
<img alt="Function Count" src="https://img.shields.io/badge/-148%20functions-13708a">
<img alt="Function Count" src="https://img.shields.io/badge/-149%20functions-13708a">
<br>
<a href="https://github.com/vueuse/vueuse" target="__blank"><img alt="GitHub stars" src="https://img.shields.io/github/stars/vueuse/vueuse?style=social"></a>
</p>
Expand Down
7 changes: 7 additions & 0 deletions indexes.json
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions packages/functions.md
Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions packages/shared/index.ts
Expand Up @@ -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'
20 changes: 20 additions & 0 deletions 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!')
})
```
16 changes: 16 additions & 0 deletions 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)
})
})
21 changes: 21 additions & 0 deletions 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<T extends Readonly<WatchSource<unknown>[]>, Immediate extends Readonly<boolean> = false>(source: T, cb: WatchCallback<MapSources<T>, MapOldSources<T, Immediate>>, options?: WatchOptions<Immediate>): void

export function watchOnce<T extends Readonly<WatchSource<unknown>[]>, Immediate extends Readonly<boolean> = false>(source: T, cb: WatchCallback<MapSources<T>, MapOldSources<T, Immediate>>, options?: WatchOptions<Immediate>): void

export function watchOnce<T, Immediate extends Readonly<boolean> = false>(sources: WatchSource<T>, cb: WatchCallback<T, Immediate extends true ? T | undefined : T>, options?: WatchOptions<Immediate>): void

// implementation
export function watchOnce<Immediate extends Readonly<boolean> = false>(
source: any,
cb: any,
options?: WatchOptions<Immediate>,
): void {
const stop = watch(source, (...args) => {
stop()
return cb(...args)
}, options)
}

0 comments on commit 098639b

Please sign in to comment.