在Vue 3中,ref
和 reactive
是两种响应式数据引用的方式,它们有不同的特点和适用场景。
ref
和 reactive
的区别ref
:
ref
是用来创建一个包装对象(wrapper object)的引用,它会将基本数据类型(如数字、字符串等)转换成一个可响应的对象。在创建 ref 时,会返回一个带有 value 属性的对象。ref
创建的对象是具有 value 属性的对象,操作时需要通过 .value
来访问其真实的值。reactive
:
reactive
是用来创建一个可响应的对象引用。它将整个对象转换成可响应的对象,对象的属性都会变成响应式的。reactive
创建的对象本身就是一个响应式对象,不需要额外的 .value
属性来访问其值。ref
适合管理简单的数据,比如管理一个数字、字符串等。reactive
适合管理复杂的数据,比如一个对象包含多个属性的对象或者数组。ref
的源码解读:javascriptexport function ref(value) {
return createRef(value)
}
function createRef(value, shallow = false) {
// 创建一个代理对象,value 存在在 inner 中
const r = {
_v_isRef: true,
get value() {
track(r, TrackOpTypes.GET, 'value')
return shallow ? value : _shallowRef(value)
},
set value(newVal) {
if (hasChanged(toRaw(newVal), value)) {
value = shallow ? newVal : convert(newVal)
trigger(r, TriggerOpTypes.SET, 'value', __DEV__ ? { newValue: newVal } : void 0)
}
}
}
return r
}
以上代码简要解读如下:
ref
函数内部调了 createRef
,并传入初始值 value
。createRef
内部创建了一个带有 _v_isRef
标志和 value
存取器属性的对象。value
存取器属性内部用了 track
方法进行追踪,并在设置新值时触发 trigger
。reactive
的源码解读:javascriptexport function reactive(target) {
if (readonlyToRaw.has(target) || reactiveToRaw.has(target)) {
return target
}
return createReactiveObject(
target,
mutableHandlers,
mutableCollectionHandlers
)
}
function createReactiveObject(target, baseHandlers, collectionHandlers) {
// ... 省略部分代码
const observed = new Proxy(target, collectionTypes.has(target) ? collectionHandlers : baseHandlers)
return observed
}
以上代码简要解读如下:
reactive
函数内部创建了一个代理对象 observed
,并返回这个代理对象。ref
适用于管理简单的数据,返回的对象具有 .value
属性。reactive
适用于管理复杂的对象状态,返回的对象本身就是具有响应性的。ref
和 reactive
的实现分基于 createRef
和 createReactiveObject
函数,通过 Proxy 对象进行了响应式的处理。当然,让我来替换一下原文中的特殊字符。请稍等片刻。在Vue 3中,ref
和 reactive
是两种响应式数据引用的方式,它们有不同的特点和适用场景。ref
和 reactive
的区别ref
:
ref
是用来创建一个包装对象(wrapper object)的引用,它会将基本数据类型(如数字、字符串等)转换成一个可响应的对象。在创建 ref 时,会返回一个带有 value 属性的对象。ref
创建的对象是具有 value 属性的对象,操作时需要通过 .value
来访问其真实的值。reactive
:
reactive
是用来创建一个可响应的对象引用。它将整个对象转换成可响应的对象,对象的属性都会变成响应式的。reactive
创建的对象本身就是一个响应式对象,不需要额外的 .value
属性来访问其值。ref
适合管理简单的数据,比如管理一个数字、字符串等。reactive
适合管理复杂的数据,比如一个包含多个属性的对象或者数组。ref
的源码解读:javascriptexport function ref(value) {
return createRef(value)
}
function createRef(value, shallow = false) {
// 创建一个代理对象,value 存在在 inner 中
const r = {
_v_isRef: true,
get value() {
track(r, TrackOpTypes.GET, 'value')
return shallow ? value : _shallowRef(value)
},
set value(newVal) {
if (hasChanged(toRaw(newVal), value)) {
value = shallow ? newVal : convert(newVal)
trigger(r, TriggerOpTypes.SET, 'value', __DEV__ ? { newValue: newVal } : void 0)
}
}
}
return r
}
以上代码简要解读如下:
ref
函数内部调了 createRef
,并传入初始值 value
。createRef
内部创建了一个带有 _v_isRef
标志和 value
存取器属性的对象。value
存取器属性内部用了 track
方法进行追踪,并在设置新值时触发 trigger
。reactive
的源码解读:javascriptexport function reactive(target) {
if (readonlyToRaw.has(target) || reactiveToRaw.has(target)) {
return target
}
return createReactiveObject(
target,
mutableHandlers,
mutableCollectionHandlers
)
}
function createReactiveObject(target, baseHandlers, collectionHandlers) {
// ... 省略部分代码
const observed = new Proxy(target, collectionTypes.has(target) ? collectionHandlers : baseHandlers)
return observed
}
以上代码简要解读如下:
reactive
函数内部创建了一个代理对象 observed
,并返回这个代理对象。ref
适用于管理简单的数据,返回的对象具有 .value
属性。reactive
适用于管理复杂的对象状态,返回的对象本身就是具有响应性的。ref
和 reactive
的实现分基于 createRef
和 createReactiveObject
函数,通过 Proxy 对象进行了响应式的处理。本文作者:姚文罡
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!