reactive函数

承上启下

在上一节 ref() 函数中,我们大致理解了 ref() 函数的作用是用来将数据转化为响应式的。但是对于基本类型和引用类型,Vue3底层做的转换不一致:对于基本类型,Vue3 通过 ref() 函数将变量转化为了 RefImpl引用对象从而实现响应式,对于引用类型,Vue3 通过ref()函数将变量转化为 RefImpl引用对象,采用基于 ES6的Proxy 的 reactive 函数,对于变量值实现响应式(包含深层响应)。

reactive 定义一个基础类型的响应式数据

定义一个对象内类型的响应式数据( 基本类型只能使用 ref() 函数转化为响应式 ),我们可以用 reactive 定义一个基本类型的值来试试

javascript 复制代码
<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 函数是否能将 引用类型数据转化为响应式。

javascript 复制代码
<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 定义一个数组类型的响应式数据

javascript 复制代码
<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 定义一个深层嵌套对象类型的响应式数据

javascript 复制代码
<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 推荐只使用 代理对象进行数据操作

不足:

  1. 有限的值类型 :它只能用于对象类型 (对象、数组和如 MapSet 这样的集合类型)。它不能持有如 stringnumberboolean 这样的原始类型

  2. 不能替换整个对象: 由于 Vue 的响应式跟踪是通过属性访问实现的,因此我们必须始终保持对响应式对象的相同引用,如果替换整个对象,那么初始的响应式关联会丢失

    javascript 复制代码
    let state = reactive({ count: 0 })
    
    // 上面的 ({ count: 0 }) 引用将不再被追踪
    // (响应性连接已丢失!)
    state = reactive({ count: 1 })
  3. 对于解构操作不友好 :当我们将响应式对象的基础类型属性解构为本地变量时,或者将该属性传递给函数时,我们将丢失响应性连接:

javascript 复制代码
const state = reactive({ count: 0 })

// 当解构时,count 已经与 state.count 断开连接
let { count } = state
// 不会影响原始的 state
count++

// 该函数接收到的是一个普通的数字
// 并且无法追踪 state.count 的变化
// 我们必须传入整个对象以保持响应性
callSomeFunction(state.count)
相关推荐
编程零零七1 小时前
Python数据分析工具(三):pymssql的用法
开发语言·前端·数据库·python·oracle·数据分析·pymssql
北岛寒沫2 小时前
JavaScript(JS)学习笔记 1(简单介绍 注释和输入输出语句 变量 数据类型 运算符 流程控制 数组)
javascript·笔记·学习
everyStudy2 小时前
JavaScript如何判断输入的是空格
开发语言·javascript·ecmascript
(⊙o⊙)~哦3 小时前
JavaScript substring() 方法
前端
无心使然云中漫步4 小时前
GIS OGC之WMTS地图服务,通过Capabilities XML描述文档,获取matrixIds,origin,计算resolutions
前端·javascript
Bug缔造者4 小时前
Element-ui el-table 全局表格排序
前端·javascript·vue.js
xnian_4 小时前
解决ruoyi-vue-pro-master框架引入报错,启动报错问题
前端·javascript·vue.js
罗政5 小时前
[附源码]超简洁个人博客网站搭建+SpringBoot+Vue前后端分离
vue.js·spring boot·后端
麒麟而非淇淋5 小时前
AJAX 入门 day1
前端·javascript·ajax
2401_858120535 小时前
深入理解MATLAB中的事件处理机制
前端·javascript·matlab