简单直观的搞懂Vue3的ref、reactive、toRef、toRefs

转载:https://blog.csdn.net/weixin_45517927/article/details/116016436

相对于Vue2来说,Vue3最大的突破就是 Composition API 。与现有的 Option API 截然不同。他的好处可以总结为两点

更集中的逻辑关注点

更方便的函数逻辑复用机制

不整废话,直接上货。

作用

首先需要明确这四个函数都是用于在 setup 中创造 响应式变量 的。明确了这一前提,再分类讨论。

区分

这四个函数分为两类,可触发页面改变与不可触发页面改变。在我没有完全搞懂每个函数具体的作用时,对这四个各面临的场景及各自的特性是不大能有一个明确的理解的。很容易被混淆。

ref、reactive 可触发页面改变

区别

ref可用于任何类型的数据创建响应式,reactive只用于创建引用类型数据的响应式。

注意

ref对引用类型变量创建响应式其根本是当你给ref传入引用类型则调用reactive方法为其创建响应式。

我为input进行双向绑定 ref 创建的数据,并且注册一个input事件来查看对原始数据的影响。

ref

// template 
<div>
    <input type="text" v-model="refVal" @input="inputRefHander" />
    {{ refVal }}
</div>

// js
let otherName = 'chris';
const refVal = ref(otherName);
const inputRefHander = () => {
    console.log(`ref:::refVal: ${refVal.value}, 原始数据: ${otherName}`);
}

通过打印出来的信息可以查看,ref 并不会影响原始数据。

注意: ref返回一个对象,所以在非模板中,使用 ref 创建的变量应通过 .value 的形式访问变量值。在模板中则不用,它会自动展开为内部值。

reactive

我同样对input做相同操作监测 reactive 返回的数据变化。

// template 
<div>
    <input type="text" v-model="reactiveVal.target" @input="inputreactiveHander" />
    {{ reactiveVal.target }}
</div>

// js
const obj = { type: 'obj', target: '5' }
const reactiveVal = reactive(obj);
const inputreactiveHander = () => {
    console.log('reactive:::', reactiveVal, "原始数据:::", obj);
}

通过打印可以很明显的看出,原始数据也被改变。

注意:

不可使用解构的方式定义响应式变量,会破坏响应性。所以老老实实的去访问属性就完事儿了,不要图那一两个单词的便利。

toRef、toRefs 不可触发页面改变

上面两个介绍了,ref 和 reactive 可以改变页面。接下来这两个则不能去改变页面,但是数据还是会遵循响应式。

区别、特点:

toRef 用于创建对象指定的属性响应式,换句话说就是只能控制一个对象中的一个属性。

toRefs 用于创建对象响应式。

他们对响应式的处理你可以理解为: toRef 类似 ref, toRefs 类似 reactive

toRef

还是同样的配方,还是同样的代码

// template
<div class="item">
    <input type="text" v-model="toRefVal" @input="inputToRefHander" />
    {{ toRefVal }}
</div>

// js
const obj = { type: 'obj', target: '5' }
const toRefVal = toRef(obj, 'target');
const inputToRefHander = () => {
      console.log("toRef:::", toRefVal, "原始数据:::", obj);
}

toRef 接受两个参数:

  1. 需要给属性创建响应式的对象
  2. 需要创建响应式的属性

通过打印的结果很容易看出,toRef是能改变原始数据的。从页面上也能看出,并不能触发页面改变。

toRefs
// template
<div>
    <input type="text" v-model="target" @input="inputToRefsHander" />
    {{ target }}
</div>

// js
const obj = { type: 'obj', target: '5' }
const { target } = toRefs(obj);
const inputToRefsHander = () => {
    console.log("toRefs:::", target, "原始数据:::", obj);
}

依旧从打印结果中可以看出,原始数据被改变,页面没有被触发。但从我的写法上应该可以注意到,toRefs 返回的对象,随便解、随便构。丝毫不会影响值的响应性。

到这里也就写完了,不过还是要提一句setup基础知识。

ref、reactive、toRef、toRefs 这些方法 均需从 vue 中导入到组件。

ref、reactive、toRef、toRefs 创建的变量在 setup 中都需要 return { ... } 抛出才可在页面使用,除非你是为props创建响应式。

最后总结成表格方便大家忘记特性的时候查阅,不过这么简单应该不会忘记( 没错,我就是单纯的想整个表格 )。

类型 是否触发页面改变 是否可以解构

ref      是 否

reactive   是 否

toRef   否 否

toRefs   否 是