ref
和 reactive
区别
在 Vue 3 中, ref
和 reactive
是用于创建响应式数据的两种方式,它们有一些区别和原理。
-
区别:
ref
:ref
函数用于创建一个包装后的响应式引用对象。它返回一个具有.value
属性的对象,该属性包含实际的值。当访问或修改ref
对象时,需要使用.value
属性。例如:const count = ref(0); console.log(count.value);
reactive
:reactive
函数用于创建一个响应式代理对象。它接收一个普通的 JavaScript 对象,并返回一个代理对象。通过代理对象访问属性时,会自动追踪属性的依赖关系。例如:const state = reactive({ count: 0 }); console.log(state.count);
-
原理:
ref
:ref
函数会将传入的值包装成一个响应式引用对象。当访问引用对象时,会返回.value
属性的值。当修改引用对象时,会触发更新通知,使得相关的组件重新渲染。reactive
:reactive
函数会使用 JavaScript 的 Proxy 对象创建一个响应式代理对象。通过代理对象访问属性时,会触发 getter 和 setter,从而追踪属性的依赖关系。当属性被修改时,会触发更新通知,使得相关的组件重新渲染。
总的来说, ref
和 reactive
都可以用于创建响应式数据,但在使用方式和语义上有一些区别。 ref
适用于创建单个值的响应式数据,而 reactive
适用于创建包含多个属性的响应式对象。
ref的原理及其简化源码
ref
函数是 Vue 3 中用于创建响应式引用对象的函数。它的原理是通过创建一个包装对象来实现响应式。
以下是 ref
函数的大致源码示例:
function ref(value) {
// 创建一个响应式对象
const obj = {
value: value
};
// 为 value 属性创建 getter 和 setter
Object.defineProperty(obj, 'value', {
get() {
// 在 getter 中追踪依赖
track(obj, 'value');
return value;
},
set(newValue) {
if (newValue !== value) {
// 更新值
value = newValue;
// 触发更新
trigger(obj, 'value');
}
}
});
return obj;
}
在上面的源码示例中, ref
函数接收一个初始值,并创建一个包含 value
属性的对象。通过 Object.defineProperty
方法,为 value
属性创建了一个 getter 和 setter。在 getter 中,会调用 track
函数来追踪依赖,确保在属性被访问时能够收集相关的依赖。在 setter 中,如果新值与旧值不相等,会更新值并触发更新,调用 trigger
函数通知相关的依赖进行更新。
通过这种方式, ref
函数创建的对象就具有了响应式的特性,当 value
属性被访问或修改时,会自动触发相关的依赖更新。
需要注意的是,以上源码示例只是简化的示例,实际的 Vue 3 源码中还有更多的细节和处理逻辑。如果您对 Vue 3 的源码感兴趣,建议查阅 Vue 3 的官方源码仓库。
ref的原理及其简化源码
reactive
函数是 Vue 3 中用于创建响应式代理对象的函数。它的原理是通过使用 JavaScript 的 Proxy 对象来实现响应式。
以下是 reactive
函数的大致源码示例(部分简化):
function reactive(obj) {
// 创建一个响应式代理对象
const observed = new Proxy(obj, {
get(target, key, receiver) {
const value = Reflect.get(target, key, receiver);
// 在 getter 中追踪依赖
track(target, key);
return isObject(value) ? reactive(value) : value;
},
set(target, key, value, receiver) {
const oldValue = Reflect.get(target, key, receiver);
const result = Reflect.set(target, key, value, receiver);
if (result && oldValue !== value) {
// 触发更新
trigger(target, key);
}
return result;
},
// 其他针对 deleteProperty、has 等操作的处理
});
return observed;
}
在上面的源码示例中, reactive
函数接收一个普通的 JavaScript 对象 obj
,并使用 Proxy
对象创建了一个响应式代理对象 observed
。通过代理对象的 getter 和 setter,实现了对属性的拦截和追踪。
在 getter 中,通过 Reflect.get
获取属性值,并在追踪依赖后返回。如果属性值是对象,会递归调用 reactive
函数,将其转换为响应式对象。
在 setter 中,通过 Reflect.set
设置属性值,并在新值与旧值不相等时触发更新,调用 trigger
函数通知相关的依赖进行更新。
通过这种方式, reactive
函数创建的对象就具有了响应式的特性,当属性被访问或修改时,会自动触发相关的依赖更新。
需要注意的是,以上源码示例只是简化的示例,实际的 Vue 3 源码中还有更多的细节和处理逻辑。如果您对 Vue 3 的源码感兴趣,建议查阅 Vue 3 的官方源码仓库。