一、关于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 类型的话不会失去响应式
<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 在模板中的解包