reactive与ref函数的应用场景分别是什么,该怎样用
Admin 2022-08-09 群英技术资讯 1528 次浏览
这篇文章主要讲解了“reactive与ref函数的应用场景分别是什么,该怎样用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“reactive与ref函数的应用场景分别是什么,该怎样用”吧!而且我们在使用时一直被告知 ref 用于创建基础类型的响应式,也可以创建引用类型的响应式。而对于引用类型,底层也是转换为 reactive 来进行响应式处理。那既然这样为撒还需要 reactive ,全部使用 ref 不就行了吗?
虽然 ref 创建的响应式数据在脚本中需要通过 .value 才能访问到呀!但是这里肯定影响不大。并且在模板中会自动添加上 .value,所以模板中不需要通过 .value 访问。
既然这二者基本没撒差别,但是还是暴露了 reactive 这个 API,难道有什么场景是 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);

我们通过源码来分析了两个响应式 API,发现 Vue3 中有没有 reactive 能做而 ref 做不了的场景?
结论是:没有
简单来说 ref 是在 reactive 上在进行了封装进行了增强,所以在 Vue3 中 reactive 能做的,ref 也能做,reactive 不能做的,ref 也能做。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
这篇文章主要介绍了CocosCreator制作射击游戏,各个方面都讲的比较详细,希望同学们自己动手试一下
本文给大家分享的是window下自带name的属性的内容,一些朋友可能对于window的name属性的作用和使用等等,不是很了解,对此这本文就简单的介绍一下,接下来我们一起了解看看吧。
微信小程序实现上传视频功能 本文实例为大家分享了微信小程序上传视频,供大家参考,具体内容如下 微信开发者工具需要安装ffmpeg环境才能正常使用下面的官方方法. 1.调用官方提供的方法(wx.chooseMedia) choosevideo(){ let that=this console.log("上传视频的方法") wx.chooseMedia({ count: 1, //上传视频的个数 mediaType:['video'], //限制上传的类型 ...
本文主要介绍了浅谈JS数组内置遍历方法有哪些和区别,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
这篇文章主要为大家介绍了js前端获取用户位置及ip属地信息示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
成为群英会员,开启智能安全云计算之旅
立即注册关注或联系群英网络
7x24小时售前:400-678-4567
7x24小时售后:0668-2555666
24小时QQ客服
群英微信公众号
CNNIC域名投诉举报处理平台
服务电话:010-58813000
服务邮箱:service@cnnic.cn
投诉与建议:0668-2555555
Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 ICP核准(ICP备案)粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008