Here’s a list of API with some notes on usage within the example component at the bottom. There are caveats to and warnings about their usage. The API list copied from docs is followed by a code snippet that uses some of the API, mentioning some of the caveats as comments, with a simple code reuse example. If you’re already familiar with the front end and Vue 1 then reading the API docs is better than the introductory docs.
The composition API offers better type checking because there’s less transpilation, which is what options API needs. The reason it’s called composition API is that mixins may have namespace collisions and don’t expose their API (return refs for example for two-way binding). Directives/options API has also changed and increased from Vue 2.
Deeply reactive value that in comparison to reactive is only useful in controlling reactivity, interfacing with reusable functions, or compensating for other reactive wrapped values’ shortfalls. That along with reactive wrapper is useState of React. What sets ref apart is that you can pass it reactive values and it will mirror changes from the original value/copy. It’s better for composition, but reactive is better for convenience.
1
2
3
4
function ref < T > (value: T): Ref < UnwrapRef < T >>
interface Ref < T > {
value: T
}
It’s meant to be side-effect free, but is similar to reactive wrapping.
1
2
3
4
5
6
7
function computed < T > (
options: {
get: () => T
set: (value: T) => void
},
debuggerOptions ? : DebuggerOptions
): Ref < T >
Returns a deep proxy object, the go-to wrapper for data.
1
function reactive < T extends object > (target: T): UnwrapNestedRefs < T >
Intended to avoid exposing exported values to misuse.
1
2
3
function readonly < T extends object > (
target: T
): DeepReadonly < UnwrapNestedRefs < T >>
Flush: ‘pre’ option, cleanup is run before effect. It’s analogous to useEffect in React. It doesn’t really watch the effect, except that it will run a cleanup function before the effectful function, triggered by the observed change in reactive value within the body.
1
2
3
4
5
6
7
8
9
10
11
function watchEffect(
effect: (onCleanup: OnCleanup) => void,
options ? : WatchEffectOptions
): StopHandle
type OnCleanup = (cleanupFn: () => void) => void
interface WatchEffectOptions {
flush ? : 'pre' | 'post' | 'sync' // default: 'pre'
onTrack ? : (event: DebuggerEvent) => void
onTrigger ? : (event: DebuggerEvent) => void
}
type StopHandle = () => void
1
watchPostEffect() //post not pre like in watchEffect
1
watchSyncEffect() //sync not pre like in watchEffect
A much more granular and asynchronous variant of watchEffect, https://vuejs.org/api/reactivity-core.html#watch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// watching single source
function watch < T > (
source: WatchSource < T > ,
callback: WatchCallback < T > ,
options ? : WatchOptions
): StopHandle
// watching multiple sources
function watch < T > (
sources: WatchSource < T > [],
callback: WatchCallback < T[] > ,
options ? : WatchOptions
): StopHandle
type WatchCallback < T > = (
value: T,
oldValue: T,
onCleanup: (cleanupFn: () => void) => void
) => void
type WatchSource < T > = |
Ref < T > // ref
|
(() => T) // getter
|
T extends object ?
T :
never // reactive object
interface WatchOptions extends WatchEffectOptions {
immediate ? : boolean // default: false
deep ? : boolean // default: false
flush ? : 'pre' | 'post' | 'sync' // default: 'pre'
onTrack ? : (event: DebuggerEvent) => void
onTrigger ? : (event: DebuggerEvent) => void
}
1
function isRef < T > (r: Ref < T > | unknown): r is Ref < T >
Accessor to ref’s value property that won’t throw when taking plain value either.
1
function unref < T > (ref: T | Ref < T > ): T
May be used to work with undefined state keys or syncing reactive property within reusable functions.
1
2
3
4
5
6
7
function toRef < T extends object, K extends keyof T > (
object: T,
key: K,
defaultValue ? : T[K]
): ToRef < T[K] >
type ToRef < T > = T extends Ref ? T : Ref < T >
Used to permit destructuring of method call output. It’s meant to be used in a reusable function call as a param.
1
2
3
4
5
6
7
function toRefs < T extends object > (
object: T
): {
[K in keyof T]: ToRef < T[K] >
}
type ToRef = T extends Ref ? T : Ref < T >
1 2
isProxy(): Reactive and friends return proxy
1
isReactive()
1
isReadonly()
Performance ref, use cases in docs.
1
2
3
4
5
function shallowRef < T > (value: T): ShallowRef < T >
interface ShallowRef < T > {
value: T
}
Used to trigger watchers after deep mutation.
1
function triggerRef(ref: ShallowRef): void
Basic usage in example at the bottom.
1
2
3
4
5
6
7
8
9
function customRef < T > (factory: CustomRefFactory < T > ): Ref < T >
type CustomRefFactory < T > = (
track: () => void,
trigger: () => void
) => {
get: () => T //track(); return val results in generic ref
set: (value: T) => void //trigger() goes here
}
1
function shallowReactive < T extends object > (target: T): T
1
function shallowReadonly < T extends object > (target: T): Readonly < T >
It’s for referencing a value without causing extra triggers or trackers in watchers, it isn’t only for performance, but also to control flow.
1
function toRaw < T > (proxy: T): T
To nest object in proxy without reactivity.
1
function markRaw < T extends object > (value: T): T
It will bundle watchers together if in the run callback body to stop them simultaneously.
1
2
3
4
5
6
function effectScope(detached ? : boolean): EffectScope
interface EffectScope {
run < T > (fn: () => T): T | undefined // undefined if scope is inactive
stop(): void
}
1
function getCurrentScope(): EffectScope | undefined
May be used as onUnmounted.
1
function onScopeDispose(fn: () => void): void
The rest of these API are not dissimilar to old options APIs. Every single one of these takes a callback that doesn’t get any params unless otherwise specified through types in the list.
1 2 3 4 5 6
onMounted() onUpdated() onUnmounted() onBeforeMount() onBeforeUpdate() onBeforeUnmount()
1
2
3
4
5
6
7
function onErrorCaptured(callback: ErrorCapturedHook): void
type ErrorCapturedHook = (
err: unknown,
instance: ComponentPublicInstance | null,
info: string
) => boolean | void
1 2 3 4 5
onRenderTracked() //dev only onRenderTriggered() //dev only onActivated() onDeactivated() onServerPrefetch()
Reuse and composition example. This can be used in any component.
1
2
3
4
5
6
7
8
9
10
11
12
function useCounter() {
const count = ref(0)
function increment() {
count.value++
}
return {
count,
increment
}
}
Setup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
setup(props, {
attrs,
slots,
emit,
expose
}: context) {
props.title //don’t destructure along with attrs and slots, they will lose reactivity
useSomeFeature(toRef(props, 'title')) //ref input expected, so toRef is used
// attributes (Non-reactive object, equivalent to $attrs), but is updated between renders
console.log(context.attrs)
// slots (Non-reactive object, equivalent to $slots)
console.log(context.slots)
// Emit events (Function, equivalent to $emit)
console.log(context.emit)
const count = ref(0)
const plusOne = computed({
get: () => count.value + 1,
set: (val) => {
count.value = val - 1
},
onTrack(e) {
debugger
},
onTrigger(e) {
debugger
}
})
plusOne.value = 1
const obj = reactive({
a: 1
})
obj.count = plusOne
obj.count++
PlusOne == obj.count // true, deep binding and unwrapping, except for collections
const increment = () => ++count.value
// Explicitly expose public properties in parent template ref
//readOnly akin to reactive
const stop = watchEffect(async (onCleanup) => {
const {
response,
cancel
} = doAsyncWork(id.value)
// `cancel` will be called if `id` changes
// so that previous pending request will be cancelled
// if not yet completed
onCleanup(cancel)
data.value = await response
})
// when the watcher is no longer needed:
stop()
watchEffect(async (onCleanup) => {
const {
response,
cancel
} = doAsyncWork(id.value)
// `cancel` will be called if `id` changes
// so that previous pending request will be canceled
// if not yet completed
onCleanup(cancel)
data.value = await response
})
const state = reactive({
count: 0
})
watch(
() => state,
(newValue, oldValue) => {
// newValue === oldValue in deep mutations which reactive values always are
}, {
deep: true
}
)
expose({
increment // exposes to parent increment function, if setup returns dom, or to encapsulate component api in single file components
})
const scope = effectScope()
scope.run(() => {
const doubled = computed(() => counter.value * 2)
watch(doubled, () => console.log(doubled.value))
watchEffect(() => console.log('Count: ', doubled.value))
})
// to dispose all effects in the scope
scope.stop()
const {
count: reusableCount,
increment: reusableIncrement
} = useCounter() //definition above
return () => h('div', count.value)
Set up return for HTML tag within the same file, but without Single-File Components (SFC). SFC require transcompiler configuration.
1 2 3 4
return { state, increment }
Single File Component structure, note absence of any return.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script setup>
import { reactive } from 'vue'
const state = reactive({ count: 0 })
function increment() {
state.count++
}
</script>
<
template >
<button @click="increment">
{{ state.count }}
</button> <
/template>
}