Vue3学习之路(一)

148 阅读2分钟

Vue3响应式:ref vs reactive

ref

简单介绍一下使用方式

<template>
  <p>{{ name }}</p>
  <el-button @click="obtain">改变这个参数</el-button>
</template>

<script setup>
import { ref } from 'vue';

// 可以做基本类型和对象类型的响应式
const age = ref(18);

const obtain = ()=>{
    // 直接输出
    console.log(age.value)
    // 改变这个值
    age.value = 20
}
</script>

reactive

<template>
  <p>{{ people.name }}</p>
  <el-button @click="obtain">改变这个参数</el-button>
</template>

<script setup>
import { reactive } from 'vue';

// 只能做对象类型的响应式
const people = reactive({name:'小明'});

const obtain = ()=>{
    // 直接输出
    console.log(people.name)
    // 改变这个值
    people.name = '小红'
}
</script>

对比

在简单了解了reactiveref的使用之后,现在,不管是想要实现对象还是基本数据类型的响应式转换,都可以轻松做到了

但是!!!是否和我一样产生了几个疑问?

为什么ref创建的值获取后面要加上 .value
为什么reactive只能做对象的响应式
他们两个我们具体要使用哪个

带着这些疑问去学习这个东西

为什么ref可以做基本类型的响应式 并且后面需要加上 .value

我们了解 Proxy的都知他只能监听对象,而无法直接处理原始数据类型的数据。考虑到这一点,我们是不是可以尝试将原始数据放置在对象中,以便Proxy进行监听呢

function ref(value) {
  // 将传入的初始值存在reactiveObj中
  const reactiveObj = { value };
  // 返回一个Proxy代理
  return new Proxy(reactiveObj, {
    // 读取数据
    get(target) {
      console.log('获取');
      return target.value;
    },
    
    // 更新数据
    set(target, property, value, ) {
      target.value = value
      console.log('更新');
      return 'set';
    },
  });
}

// 测试
const count = ref(100000);
count.value // 输出'get'
count.value = 1; // 输出'set'

在这个ref的封装过程中,我们将值包装在一个对象的value属性中,这个过程就解释了为什么我们需要使用.value来访问和修改ref封装返回的值

同样,这里不管传入的数据是对象类型还是基本数据类型,都会经过这个函数包装将其放在一个对象里,然后再使用Proxy监听包装后的对象,所以才让ref具备同时代理原始数据和对象数据的能力。

为什么reactive只能做对象的响应式

// 定义一个对象
let testObj = {
  name: '11'
};

// 将对象传入Proxy中,并传入处理器对象来重写它的get和set方法
const proxyObj = new Proxy(testObj, {
  get: () => {
    // 获取数据的时候输出‘get’
    console.log('get');
  },

  set: () => {
    // 设置数据的时候输出‘set’
    console.log("set");
    return 'set';
  }
});

// 实验数据是否正常被监听了
proxyObj.name
proxyObj.name = '22';

// 因为reactive使用 Proxy 来实现数据劫持的。只要了解了`Proxy`的特性,就能明白为什么`reactive`不支持原始数据类型了
// 如果是基本类型就会报错: Cannot create proxy with a non-object as target or handler

现在了解需要使用ref还是reactive了吗?

以上仅个人理解,欢迎大家补充👏