您的位置:首页 > 教育 > 培训 > reactive函数

reactive函数

2024/10/5 17:21:58 来源:https://blog.csdn.net/qq_40792800/article/details/140817882  浏览:    关键词:reactive函数

承上启下

在上一节 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 = 999console.log(userInfo,'userInfo');}return {userInfo,change,};},
};
</script>

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

这能证明 reactive() 函数也能将深层嵌套对象转化为响应式数据

总结

作用:定义一个 对象类型的响应式数据( 基本类型还请使用 ref()函数转化 )

语法:let 代理对象 = reactive(源对象)。接收一个对象或数组,返回一个代理对象

深度:reactive() 定义的响应式数据时深层次的,嵌套的对象或数组中的对象都能响应

底层:内部基于 ES6 的 Proxy实现,通过代理对象操作源对象内部数据进行操作

代理对象 Proxy 和 源对象 并不全等,只有代理对象是响应式的,更改原始对象不会触发更新。所以Vue3 推荐只使用 代理对象进行数据操作

不足:

  1.  有限的值类型:它只能用于对象类型 (对象、数组和如 MapSet 这样的集合类型)。它不能持有如 stringnumber 或 boolean 这样的原始类型。
  2. 不能替换整个对象:由于 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)

         

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com