计算属性
# 计算属性
- 使用
<template>
<button @click="changeName">
change name
</button>
</template>
<script setup lang="ts">
import { computed, ref } from "vue"
let first = ref("zhang")
let lase = ref("san")
// 1.选项式写法, 支持一个对象,传入get函数以及set函数自定义操作
let name = computed({
get (){
return first.value +"_"+ last.value
},
set (newVal){
[first.value, last.value] = newVal.split("-")
}
})
const changeName = ()=>{
name.value = "li-si"
name2.value = "wangwu" // error: 无法为“value”赋值,因为它是只读属性。
}
// 2. 函数式写法,只能支持一个getter函数,不允许修改值
//!!!
let name2 = computed(()=>{
return first.value +"_"+ last.value
})
</script>
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
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
- 原理
// 1. 格式化参数:
computed函数中传入的参数式是什么类型
如果是函数,则在setter中提醒
如果为对象,则读取对象中的get与set函数;
//2. 将参数传入computedRefImpl函数
定义了`dirty`用于脏值检测,如果为true则会读取缓存中的值,如果为false则会重新计算
定义effect, 用于收集依赖获取计算值
定义value,用于返回计算值
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
- 源码
// ReactiveEffect(fn, scheduler = null, scope)
// fn: getter函数,
// scheduler: 调度函数
var _a;
class ComputedRefImpl {
constructor(getter, _setter, isReadonly, isSSR) {
this._setter = _setter;
this.dep = undefined;
this.__v_isRef = true;
this[_a] = false;
this._dirty = true;
//1.1 第一次进入时不会执行,因为第一次执行完`_dirty`的值为false,
//1.2 当计算的值发生变化,则触发scheduler将_dirty改为ture
this.effect = new ReactiveEffect(getter, () => {
if (!this._dirty) {
this._dirty = true;
triggerRefValue(this);
}
});
this.effect.computed = this;
this.effect.active = this._cacheable = !isSSR;
this["__v_isReadonly" /* ReactiveFlags.IS_READONLY */] = isReadonly;
}
get value() {
const self = toRaw(this);
trackRefValue(self);
// 1.0 第一次进入后,会将dirty该为false,同时去收集依赖计算值
if (self._dirty || !self._cacheable) {
self._dirty = false;
self._value = self.effect.run();
}
return self._value;
}
set value(newValue) {
this._setter(newValue);
}
}
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
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
编辑 (opens new window)
上次更新: 2023/05/16, 17:34:11