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)
相关推荐
永乐春秋17 分钟前
WEB攻防-通用漏洞&文件上传&js验证&mime&user.ini&语言特性
前端
鸽鸽程序猿18 分钟前
【前端】CSS
前端·css
ggdpzhk20 分钟前
VUE:基于MVVN的前端js框架
前端·javascript·vue.js
小曲曲1 小时前
接口上传视频和oss直传视频到阿里云组件
javascript·阿里云·音视频
学不会•2 小时前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html
EasyNTS3 小时前
H.264/H.265播放器EasyPlayer.js视频流媒体播放器关于websocket1006的异常断连
javascript·h.265·h.264
活宝小娜5 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点5 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow5 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o5 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app