本文小编为大家详细介绍“Vue3中reactive与ref函数使用场景是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“Vue3中reactive与ref函数使用场景是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。
我们先简单了解一下这两个 API。
返回对象的响应式副本,响应式转换是“深层”的——它影响所有嵌套 property。我们一般这样写。
const obj = reactive({ count: 0 })
并且可以直接使用。
const count = obj.count
接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象仅有一个 .value
property,指向该内部值。 我们一般是这样写。
const data = ref(xxx)
引用的时候,一般会通过data.value
的方式引用。
const dataValue = data.value
通过跟踪 Vue3 的源代码可以证明,当我们调用 ref 方法来定义响应式数据时,当参数为对象类型时,其实里面用的是 reactive 方法。也就是说上面的 data.value ,事实上是 reactive 方法创造出来的。
我们通过源码来看看 ref 的源码实现。
源码分析版本:3.2.36
function ref(value) { return createRef(value, false); }
ref 函数跳转到 createRef 函数。
function createRef(rawValue, shallow) { ... return new RefImpl(rawValue, shallow); }
createRef 函数返回的是 RefImpl 类的实例,换句话说,ref 创建出来的响应式就是 RefImpl 实例对象。
const count = ref(1); console.log(count);
我们重点来看看这个 RefImpl 类。
class RefImpl { constructor(value, __v_isShallow) { ... this._value = __v_isShallow ? value : toReactive(value); } get value() { trackRefValue(this); return this._value; } set value(newVal) { newVal = this.__v_isShallow ? newVal : toRaw(newVal); if (hasChanged(newVal, this._rawValue)) { this._rawValue = newVal; this._value = this.__v_isShallow ? newVal : toReactive(newVal); triggerRefValue(this, newVal); } } }
__v_isShallow
参数在这里默认是 false,这里也顺带讲一嘴,当我们在使用 shallowRef
时,这个参数为 true。
function shallowRef(value) { return createRef(value, true); }
Ref 与 Reactive 创建的都是递归响应的,将每一层的 json 数据解析成一个 proxy 对象,shallowRef 与 shallowReactive 创建的是非递归的响应对象,shallowReactive 创建的数据第一层数据改变会重新渲染 dom。
var state = shallowReactive({ a:'a', gf:{ b:'b', f:{ c:'c', s:{d:'d'} } } }); // 改变第一层的数据会导致页面重新渲染 state.a = '1' // 如果不改变第一层,只改变其他的数据页面不会重新渲染 state.gf.b = 2
通过 shallowRef 创建的响应式对象,需要修改整个 value 才能重新渲染 dom。
var state = shallowRef({ a:'a', gf:{ b:'b', f:{ c:'c', s:{d:'d'} } } }); // 不会重新渲染 state.value.a = 1 // 要修改整个 value 才能重新渲染 state.value = { a:'1', gf:{ b:'2', f:{ c:'3', s:{d:'d'} } } }
如果想更新 shallowRef 的某一层数据,并且想触发渲染,可以使用 triggerRef。
var state = shallowRef({ a:'a', gf:{ b:'b', f:{ c:'c', s:{d:'d'} } } }) state.value.gf.f.s.d = 4 triggerRef(state)
所以这里会走到 toReactive(value)
函数。
const isObject = (val) => val !== null && typeof val === 'object'; const toReactive = (value) => isObject(value) ? reactive(value) : value;
可以看到,如果传入的参数是一个对象的话,返回值将会继续调用 reactive 方法来进行包裹,reactive 最终会通过 Proxy 来进行实现响应拦截,返回的也是一个 Proxy 对象,但在这里不重要,我们只需要知道当 ref 的参数为对象时,用的就是 reactive 方法。
const data = reactive({ count: 1, }); console.log(data); const data_ref = ref({ count: 1, }); console.log(data_ref);
结果显然,让对 ref 传入对象作为参数时和传入基本类型作为参数返回结果情况是不一样的。
基本类型返回值value
就是具体的值,对象类型返回值value
是 reactive 方法创建的 proxy 对象。
通过源码来看,其实也证明了,在 Vue3 中,如果是把对象类型的数据弄成响应式,reactive 和 ref 都可以,且ref 内部是通过r eactive 来支持的。
也就是说,你 reactive 能做的,我 ref 也能做。
其实通过上面的例子就能知道有什么是 reactive 不能做的呢?很明显,reactive 不支持对基本类型数据响应式,也就是说基本类型数据不能直接作为 reactive 的参数来使用。
简单看看源码。
function reactive(target) { ... return createReactiveObject(...); }
reactive 函数跳转到 createReactiveObject 函数。
const isObject = (val) => val !== null && typeof val === 'object'; function createReactiveObject(...) { if (!isObject(target)) { { console.warn(`value cannot be made reactive: ${String(target)}`); } return target; } ... const proxy = new Proxy(...); proxyMap.set(target, proxy); return proxy; }
createReactiveObject 一开始就会判断 target
是否是对象,如果不是对象就会直接⚠️提示返回。如果是对象就会把 target 用 Proxy 变成响应式对象。
const data = reactive(10);
读到这里,这篇“Vue3中reactive与ref函数使用场景是什么”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。