vue3中的reactive和ref

2023-06-09 11:19:28 浏览数 (2)

一、关于reactive

reactive 接受一个对象类型的值,返回一个对象的代理。

reactive的特点

1、仅对对象类型有效(对象、数组和 Map、Set 这样的集合类型),而对 string、number 和 boolean 这样的 原始类型 无效。

代码语言:javascript复制
let count = reactive(0)
setInterval(() => {
  count   // 数据是变了,但是页面并不会变,因为不是响应式的数据
}, 2000)

2、reactive() 返回的是一个原始对象的 Proxy,它和原始对象是不相等的。

代码语言:javascript复制
let o = {name: 'zs', age: 10}
let obj = reactive(o)
console.log(obj === o) // false

3、状态都是默认深层响应式的。这意味着即使在更改深层次的对象或数组,你的改动也能被检测到。也可以直接创建一个浅层响应式对象(shallowReactive()),它们仅在顶层具有响应性。

代码语言:javascript复制
let o = {name: 'zs', info: {age: 1}}
let obj = reactive(o)
setInterval(() => {
  obj.info.age  
}, 2000)

4、响应式对象内的嵌套对象依然是代理(Proxy)

代码语言:javascript复制
let o = {name: 'zs', info: {age: 1}}
let obj = reactive(o)
console.log(obj.info) // Proxy(Object) {age: 1}

5、当响应式对象改变时,原始对象的值也会被改变

代码语言:javascript复制
<script setup>
import {reactive} from 'vue'

let o = {name: 'zs', info: {age: 1}}
let obj = reactive(o)
setInterval(() => {
  obj.info.age  
  // console.log(o);
}, 2000)
</script>

<template>
  <div>
    {{ obj }}
    <!-- {{ o }} -->
  </div>
</template>

上面的代码我发现一个奇怪的问题,当正常执行上面代码时,看不出任何问题,但是如果把下面的代码注释解除掉,就会发现怎么 o 也是响应式的了?但是在控制台中打印出来并不是响应式的啊,如果再把 obj 注释,此时 o 不是响应式的,这里其实o并不是响应式的,只是由于obj 改变会影响视图更新,重新渲染页面后,拿到最新数据,看似 o 是响应式的,实际上只是由于,obj的改变,导致 o 也改变然后视图,数据更新了而已。

reactive 的局限性

1、上面第一点。

2、将响应式对象的属性赋值或解构至本地变量时,或是将该属性传入一个函数时,我们会失去响应性。

  • 这里的属性值应该是一个基本类型,object 类型的话不会失去响应式
代码语言:javascript复制
<script setup>
import {reactive} from 'vue'

let o = {name: 'zs', info: {age: 1}}
let obj = reactive(o)
// let {info} = obj // 依旧时响应式的数据
let info = obj.info // 依旧时响应式的数据
// let age = obj.info.age // age 不是响应式的

setInterval(() => {
  info.age  
  age  
}, 2000)
</script>

<template>
  <div>
    {{ info }}
    <!-- {{ age}} -->
  </div>
</template>

二、关于 ref

ref() 方法来允许我们创建可以使用任何值类型的响应式 ref,如果我们创建的是一个对象的响应式数据,其实里面原理也是通过 reactive 实现的。

ref() 将传入参数的值包装为一个带 .value 属性的 ref 对象

ref 特点

1、一个包含对象类型值的 ref 可以响应式地替换整个对象,如果是 reactive 的话不会被换成响应式的

代码语言:javascript复制
<script setup>
let obj = ref({name: 'zs', age: 1})
obj.value = {name: 'lisi', age: 12} // 依旧是响应式的

setInterval(() => {
  obj.value.age  
}, 2000)
</script>

<template>
  <div>
    {{ obj }}
  </div>
</template>

2、ref 被传递给函数或是从一般对象上被解构时,不会丢失响应性

代码语言:javascript复制
let obj = {
  name: ref('zs'),
  age: ref(12)
}
let {age} = obj
setInterval(() => {
  age.value  
}, 2000)

注意:最外层的 obj 不能被 ref 或 reactive 设为响应式的,因为reactive结构出来的值不具有响应式。

3、ref 在模板中的解包

0 人点赞