reactive与ref函数的应用场景分别是什么,该怎样用
Admin 2022-08-09 群英技术资讯 301 次浏览
而且我们在使用时一直被告知 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进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
JS实现数组倒序排列的方法是什么?在JavaScript中,我们能用reverse() 方法来实现元素倒序排列,一些新手可能对于reverse() 方法的使用不是很了解,下面我们就来看看reverse() 是如何实现颠倒数组中元素的顺序的。
怎么使用Node.js搭建一个静态Web服务器?下面本篇文章就手把手教大家使用Node.js搭建静态Web服务器的方法,希望对大家有所帮助!
vue+elementUI配置表格的列显示与隐藏,供大家参考,具体内容如下描述:表格的列过多时,可以根据需要控制列的显示与隐藏,目前是采用Vue+elementUI(适配Vue3的Element Plus)实现的,具体效果与代码如下:效果图:完整代码:template div id=app el-table :
这篇文章主要为大家详细介绍了jquery实现手风琴展开效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
这篇文章主要为大家详细介绍了vue实现搜索小功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008