响应式数据
reactive
reactive 是进行数据监听核心,所有响应式数据都是建立在 reactive 的基础上。
const obj = reactive({
a: 0,
});
obj.a++;
ref
与 reactive 一样,使用时通过 .value 访问。
const count = ref(0);
count.value++;
customRef
自定义 ref:对数据更新做控制。比如下面是一个去除空格的例子
const str = removeSpaceRef('');
str.value = ' hello '; //--> 'hello'
function removeSpaceRef(value: string) {
return customRef((track, trigger) => ({
get() {
track(); // 收集依赖
return value;
},
set(val) {
value = val.trim();
trigger(); // 派发更新
}
}))
}
computed
计算属性:接收一个响应式数据,返回一个新的响应式数据(只读)。同样通过 .value 访问。
const a = ref(0);
const b = computed(() => a.value);
a.value++; // a 发生变化,b 也会自动更新
console.log(b.value); //--> 1
const a = ref(0);
computed({
get: () => a.value,
set(val) {
// a 被重新赋值时执行
// code...
}
});
binding
binding 是实现数据更新的核心,当 binding 使用了响应式数据(具体的值,而不是一个对象),该值发生变化,绑定的函数也会重新执行。
正因为函数中用到了响应式数据,所以 reactive 也就是 proxy.get 才能监听到,将此函数进行收集,保存在执行队列中。 为了节省内存空间,在绑定的函数返回 true 时,该函数将会执行队列中的任务进行删除. 当然,dom 的自动更新同样用到了 binding
const count = ref(0);
binding(() => { // 数据发生改变,函数即执行
console.log(count.value);
})
watchEffect
watchEffect 基于 binding 实现,因为 binding 本身就可以作为一个监听函数使用。在用法上与 vue watchEffect 一致。
const count = ref(0);
watchEffect(() => { // 数据发生改变,函数即执行
console.log(count.value);
})
watchEffect 与 binding 的区别:
- binding 可以监听整个对象,对象中的任意一个值发生变化都会触发更新;而 watchEffect 只监听用到的值;
watch
watch 基于 binding 实现,因为 binding 本身就可以作为一个监听函数使用。watch 在此基础上加了一个额外的配置参数。 在用法上与 vue watch 一致。
与 vue watch 的差异:
- 监听目标只能以一个函数形式形式传递
- 当 watch 监听目标为一个引用值时,其中回调的第二个参数 oldValue,plvue 返回的是一个非响应式旧数据。而在 vue 中返回的是该数据本身,作者认为这里返回数据本身并没有什么意义
const o = reactive({
a: 1,
b: 2,
})
const unwatch = watch(
() => o,
(value, oldValue) => {
// value !== oldValue
// code...
},
{
immediate: true, // 是否立即执行
deep: true, // 开启深度监听
}
)
binding 和 watch 的区别:
- binding 在用到对象中的某个 key 时触发更新,监听的是整个对象;
- binding 不能够进行深度监听,watch 可以;
const o = reactive({
a: 0,
b: 1,
c: {
d: 2,
},
})
binding(() => {
o.a; // o['a'|'b'|'c'] 发生变化时更新
})
binding(() => {
o.c.d; // o.a 发生变换时不会触发,因为这里监听的是 o.c 这个对象
})
watch(() => o.a, value => {
// o.a 发生变化时执行
})
watch(() => o, value => {
// o 中的任何一个值发生变化即执行
}, { deep: true })