reactive与ref函数的应用场景分别是什么,该怎样用
Admin 2022-08-09 群英技术资讯 927 次浏览
这篇文章主要讲解了“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进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
这篇文章主要介绍Vuex的作用,很多新手对于Vuex的原理、使用以及其他概念不是很了解,下面小编就带大家深入的来接Vuex,感兴趣的朋友就继续往下看吧,希望大家阅读完这篇文章能有所收获。
动态路由可以根据不同用户登录获取不一样的路由层级,可随时调配路由,下面这篇文章主要给大家介绍了关于vue实现动态路由的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
这篇文章主要介绍了uniapp和vue的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
目录前言框选的实现Group 类的实现小结前言虽然这两个月基金涨的还行,但是离回本还有一大大大段距离????。今天呢,我们要实现的是 canvas 中物体的框选功能,大概就像下面这个样子:然后话不多说,直接开撸 ✍????框选的实现先来说下拖蓝选区(鼠标拖拽区域)的实现方式吧,仔细观察你会发现选区其实就是个普通矩形,这个区域由鼠标
目录前言一、作用域(scope)1、作用域的分类二、预编译三、作用域链前言我们需要先知道的是引擎,引擎的工作简单粗暴,就是负责javascript从头到尾代码的执行。引擎的一个好朋友是编译器,主要负责代码的分析和编译等;引擎的另一个好朋友就是今天的主角--作用域。那么作用域用来干什么呢?作用域链跟作用域又有什么关系呢?
成为群英会员,开启智能安全云计算之旅
立即注册关注或联系群英网络
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备09006778号 域名注册商资质 粤 D3.1-20240008