学习vue3的响应式(ref/reactive)

vue3的响应式核心API:ref、reactive。应用场景中ref主要是用来声明基础数据类型响应式,reactive主要用来声明对象类型响应式(包括数组)。但是ref同样也能用来声明对象类型的响应式数据。

1.ref

1.1 ref基础数据类型的响应式(string,number,boolean)
const str = ref("abc");
const num = ref(0);
const flag = ref(false);
const changeStr = () => {
  console.log(str);
  str.value = str.value == "abc" ? "def" : "abc";
};
const changeNum = () => {
  num.value++;
};
const changeFlag = () => {
  flag.value = !flag.value;
};

 

从代码中可以看出,这些值的变化应该都是没有问题的,都能被响应式。str('abc'/'def'切换),num递增,flag(false/ture切换),ref包装返回的对象是RefImpl对象。从使用场景来看,RefImpl对象在script中,需要.value来获取值/修改值;在template中可以直接使用,不需要.value。

1.2 ref对象类型的响应式
const rObj = ref({
  name: "czq",
  age: 18,
});
// 修改rObj的属性
const changeRefObj = () => {
  console.log(rObj);
  console.log(rObj.value);
  rObj.value.name = "czq2";
  rObj.value.age++;
};

 

使用ref来声明对象类型的响应式数据时,返回得到RefImpl对象,并且.value中保存的是Proxy响应式代理对象,这个是ref和reactive之间的区别之一。reactive声明出来的是Proxy响应代理对象(没有RefImpl包装)。

2.reactive

2.1 reactive对象类型的响应式
const obj = reactive<any>({
  name: "czq",
  age: 18,
});
// 修改obj的属性
const changeObj = () => {
  console.log(obj);
  obj.name = "czq2";
  obj.age++;
};

通过reactive包裹返回的对象,生成了Proxy响应式代理对象,通过.来访问和修改值。那么这时候就可能又疑惑,那如果是新增属性,那会不会响应呢? 

// 添加新属性(基础类型)
const addObjKey = () => {
  obj.extra = obj.extra == undefined ? "额外添加的属性" : undefined;
};
// 修改obj新添加的属性(观察其是否具备响应式)
const changeObjNewKey = () => {
  obj.extra = "额外添加的属性2";
};

结论:Proxy响应式对象,可以监听到对象新增的属性(基础类型),对象属性如果删除了,后续再添加,也可以监听到。

2.2 探索reactive对象类型(深层对象)的响应式
const obj2 = reactive<any>({
  info: {
    name: "czq",
    age: 18,
    obj: {
      a: 1,
      b: 2,
    },
  },
});
// 对已有的深层对象属性进行修改/新增属性
const changeObj2 = () => {
  obj2.info.name = "czq2";
  obj2.info.age++;
  obj2.info.extra = "额外添加的属性";
  obj2.info.obj.a = 10;
  obj2.info.obj.b = 20;
};
// 对深层对象新增属性进行修改
const changeObj2NewKey = () => {
  obj2.info.extra = "额外添加的属性2";
};

结论: reactive包裹返回的Proxy响应式代理对象,对深层对象操作修改属性,新增属性,新增属性修改都是具备响应式的,可以被监听到。

2.3 探索reactive数组的响应式
const arr = reactive<any>([{ value: 1 }, { value: 2 }, { value: 3 }]);
const changeArr = () => {
  arr[0].value = 10;
  arr[1].value = 20;
  arr[2].value = 30;
  arr.push({ value: 4 });
};
const changeArr2 = () => {
  arr[3].value = 40;
};

结论: reactive包裹的对象为数组时,返回的Proxy响应式代理对象,数据类型为数组,对数组操作修改数组项,新增数组项,修改数组项中的属性都是具备响应式的,可以被监听到。

刚刚说的Ref包裹对象类型时,与reactive的差异。其实就是ref通过RefImpl创建实例过程,对_value进行了一次包装。判断包裹的是对象类型还是基本数据类型。如果是对象类型则使用reactive进行生成响应式代理对象。这应该就是为啥官方推荐使用ref,因为对于对象类型的响应式数据,ref也是使用reactive去实现的。

学习过程的记录图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值