承上启下
在上一节 ref() 函数中,我们大致理解了 ref() 函数的作用是用来将数据转化为响应式的。但是对于基本类型和引用类型,Vue3底层做的转换不一致:对于基本类型,Vue3 通过 ref() 函数将变量转化为了 RefImpl引用对象从而实现响应式,对于引用类型,Vue3 通过ref()函数将变量转化为 RefImpl引用对象,采用基于 ES6的Proxy 的 reactive 函数,对于变量值实现响应式(包含深层响应)。
reactive 定义一个基础类型的响应式数据
定义一个对象内类型的响应式数据( 基本类型只能使用 ref() 函数转化为响应式 ),我们可以用 reactive 定义一个基本类型的值来试试
<template>
  <p>姓名:{{ a }}</p>
  <button @click="change">点击修改</button>
</template>
<script>
import { reactive } from 'vue'
export default {
  name: "App",
 
  setup() {
    let a = reactive(666)
    console.log(a)
    function change() {
      a = 1234
    }
    return {
      a,
      change
    };
  },
};
</script>
 

我们可以看到,虽然页面上展示了正确数据,但是在控制台上Vue已经报了警告,并不建议我们这样做,此时我们点击按钮改变数据,发现数据已经改变了,但是页面并没有更新,这表示当前属性a,并不是一个响应式数据,这也表示了为什么Vue3 不建议使用reactive 来转化基础数据
reactive 定义一个基础类型的响应式 
reactive 定义一个对象类型的响应式数据
上面案例表明 reactive 函数无法将基础数据类型转化为响应式数据,那我们现在来试一试 reactive 函数是否能将 引用类型数据转化为响应式。
<template>
  <p>姓名:{{ userInfo.name }}</p>
  <p>年龄:{{ userInfo.age }}</p>
  <p>工作:{{ userInfo.work }}</p>
  <button @click="change">点击修改</button>
</template>
<script>
import { reactive } from 'vue'
export default {
  name: "App",
 
  setup() {
    let userInfo = reactive({
      name: 'al',
      age:'29',
      work:'前端'
    })
    console.log(userInfo,‘userInfo’)
    function change() {
      userInfo.name = "汤圆仔";
      console.log(userInfo);
    }
    return {
      userInfo,
      change
    };
  },
};
</script>
 
此时页面展示正确,控制台打印当前经过转化为响应式的数据。是一个 Proxy 代理对象

点击按钮修改数据后,页面展示正确,控制台上打印的 Proxy 代理对象中 name 属性值夜变化了

此时我们注意到,修改数据时,我们并没有像 ref() 函数转化响应式对象时,通过 xxx.value 来修改属性值,而是直接通过 xxx.xxx 进行修改的。
reactive 定义一个数组类型的响应式数据
<template>
  <p>工作:{{ hobby }}</p>
  <button @click="change">点击修改</button>
</template>
<script>
import { reactive } from "vue";
export default {
  name: "App",
  setup() {
    let hobby = reactive(['抽烟','喝酒','烫头']) 
    console.log(hobby);
    function change() {
      hobby[0] = '学习'
      console.log(hobby,'hobby');
    }
    return {
      hobby,
      change,
    };
  },
};
</script>
 
控制台上打印 转换过后 hobby 属性,我们发现也是一个 Proxy 代理对象,但还是一个 Array,

我们通过数组下标改变数据,点击按钮之后发现页面上数据真的修改了,在Vue2中这是行不通的:Vue2中不能通过数组下标直接修改数组,不能通过 length属性 直接设置数组长度

但是还是能证明一点,reactive() 函数能将数组数据转化为响应式数据
reactive 定义一个深层嵌套对象类型的响应式数据
<template>
  <p>工作:{{ userInfo.test.a.b.c }}</p>
  <button @click="change">点击修改</button>
</template>
<script>
import { reactive } from "vue";
export default {
  name: "App",
  setup() {
    let userInfo = reactive({
      test: {
        a: {
          b: {
            c: 666
          }
        }
      }
    });
    function change() {
      userInfo.test.a.b.c = 999
      console.log(userInfo,'userInfo');
    }
    return {
      userInfo,
      change,
    };
  },
};
</script>
 

点击按钮后,数据修改,同时页面同步更新。深层嵌套数据也被转化为 Proxy代理对象

这能证明 reactive() 函数也能将深层嵌套对象转化为响应式数据
总结
作用:定义一个 对象类型的响应式数据( 基本类型还请使用 ref()函数转化 )
语法:let 代理对象 = reactive(源对象)。接收一个对象或数组,返回一个代理对象
深度:reactive() 定义的响应式数据时深层次的,嵌套的对象或数组中的对象都能响应
底层:内部基于 ES6 的 Proxy实现,通过代理对象操作源对象内部数据进行操作
代理对象 Proxy 和 源对象 并不全等,只有代理对象是响应式的,更改原始对象不会触发更新。所以Vue3 推荐只使用 代理对象进行数据操作
不足:
-  有限的值类型:它只能用于对象类型 (对象、数组和如 
Map、Set这样的集合类型)。它不能持有如string、number或boolean这样的原始类型。 - 不能替换整个对象:由于 Vue 的响应式跟踪是通过属性访问实现的,因此我们必须始终保持对响应式对象的相同引用,如果替换整个对象,那么初始的响应式关联会丢失 
let state = reactive({ count: 0 }) // 上面的 ({ count: 0 }) 引用将不再被追踪 // (响应性连接已丢失!) state = reactive({ count: 1 }) 
3. 对于解构操作不友好:当我们将响应式对象的基础类型属性解构为本地变量时,或者将该属性传递给函数时,我们将丢失响应性连接:
const state = reactive({ count: 0 })
// 当解构时,count 已经与 state.count 断开连接
let { count } = state
// 不会影响原始的 state
count++
// 该函数接收到的是一个普通的数字
// 并且无法追踪 state.count 的变化
// 我们必须传入整个对象以保持响应性
callSomeFunction(state.count) 



















