# 计算属性和侦听器
本节使用单文件组件语法作为代码示例
# computed
传入一个 getter 函数,返回一个默认不可手动修改的 ref 对象。
const count = ref(1)
const plusOne = computed(() => count.value + 1)
console.log(plusOne.value) // 2
plusOne.value++ // 错误!
1
2
3
4
5
6
2
3
4
5
6
或者传入一个拥有 get
和 set
函数的对象,创建一个可手动修改的计算状态。
const count = ref(1)
const plusOne = computed({
get: () => count.value + 1,
set: val => {
count.value = val - 1
},
})
plusOne.value = 1
console.log(count.value) // 0
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
类型定义:
// 只读的
function computed<T>(getter: () => T): Readonly<Ref<Readonly<T>>>
// 可更改的
function computed<T>(options: { get: () => T; set: (value: T) => void }): Ref<T>
1
2
3
4
5
2
3
4
5
# watchEffect
立即执行传入的一个函数,并响应式追踪其依赖,并在其依赖变更时重新运行该函数。
const count = ref(0)
watchEffect(() => console.log(count.value))
// -> 打印出 0
setTimeout(() => {
count.value++
// -> 打印出 1
}, 100)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
类型定义:
function watchEffect(
effect: (onInvalidate: InvalidateCbRegistrator) => void,
options?: WatchEffectOptions
): StopHandle
interface WatchEffectOptions {
flush?: 'pre' | 'post' | 'sync' // default: 'pre'
onTrack?: (event: DebuggerEvent) => void
onTrigger?: (event: DebuggerEvent) => void
}
interface DebuggerEvent {
effect: ReactiveEffect
target: any
type: OperationTypes
key: string | symbol | undefined
}
type InvalidateCbRegistrator = (invalidate: () => void) => void
type StopHandle = () => void
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
参考::watchEffect
指南
# watch
watch
API 完全等效于选项 API this.$watch (以及 watch 中相应的选项)。watch
需要侦听特定的数据源,并在回调函数中执行副作用。默认情况是懒执行的,也就是说仅在侦听的源变更时才执行回调。
对比 watchEffect,watch 允许我们:
- 懒执行副作用;
- 更明确哪些状态的改变会触发侦听器重新运行副作用;
- 访问侦听状态变化前后的值。
# 侦听单个数据源
侦听器的数据源可以是一个拥有返回值的 getter 函数,也可以是 ref:
// 侦听一个 getter
const state = reactive({ count: 0 })
watch(
() => state.count,
(count, prevCount) => {
/* ... */
}
)
// 直接侦听一个 ref
const count = ref(0)
watch(count, (count, prevCount) => {
/* ... */
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 侦听多个数据源
watcher 也可以使用数组来同时侦听多个源:
watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
/* ... */
})
1
2
3
2
3
# 与 watchEffect
共享的行为
watch 和 watchEffect
在停止侦听, 清除副作用 (相应地 onInvalidate
会作为回调的第三个参数传入),副作用刷新时机 和 侦听器调试 等方面行为一致.
类型定义:
// 侦听单数据源
function watch<T>(
source: WatcherSource<T>,
callback: (
value: T,
oldValue: T,
onInvalidate: InvalidateCbRegistrator
) => void,
options?: WatchOptions
): StopHandle
// 侦听多数据源
function watch<T extends WatcherSource<unknown>[]>(
sources: T
callback: (
values: MapSources<T>,
oldValues: MapSources<T>,
onInvalidate: InvalidateCbRegistrator
) => void,
options? : WatchOptions
): StopHandle
type WatcherSource<T> = Ref<T> | (() => T)
type MapSources<T> = {
[K in keyof T]: T[K] extends WatcherSource<infer V> ? V : never
}
// 共有的属性 请查看 `watchEffect` 的类型定义
interface WatchOptions extends WatchEffectOptions {
immediate?: boolean // default: false
deep?: boolean
}
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
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
参考:watch
指南