【Vue3】05-reactive 全家桶

28 阅读2分钟

1. reactive

1.1 作用

实现引用类型的响应式

1.2 和 ref 的区别

ref 支持基本类型和引用类型,而 reactive 只支持引用类型
② 在 js 中取值,ref 要写 .value,而 reactive 不用

1.3 注意点

如果对 reactive 对象直接重新赋值,会失去响应式
对象的示例
let obj = reactive({name:'lzy', age: 18})
console.log(obj)  // Reactive< Object>

obj = {name:'LZY', age: 21}
console.log(obj)  // {name: 'LZY', age: 21}
对象的解决办法
只更改对象的属性,而不改变整个变量的指向
let obj = reactive({name:'lzy', age: 18})
console.log(obj)  // Reactive< Object>

obj.name = "LZY"
console.log(obj)  // Reactive< Object>
数组的示例
let arr = reactive([1, 2, 3]) 
console.log(arr)  // Reactive<Array(3)>

arr = [4,5,6]
console.log(arr)  // (3) [4, 5, 6]
数组的解决办法
① 把整个数据内置为一个对象的属性,然后可以直接改变变量的指向
let obj = reactive({arr:[1,2,3]})
console.log(obj)  // Reactive<Object> arr:(3) [1, 2, 3]

obj.arr = [4,5,6]
console.log(obj)  // Reactive<Object> arr:(3) [4, 5, 6]
② 调用数组方法来更改,但不能直接改变变量的指向
let arr = reactive([1,2,3])
console.log(arr)  // Reactive<Object> arr:(3) [1, 2, 3]

while(arr.length){
    arr.pop() 
}
arr.push(4,5,6)
console.log(arr)  // Reactive<Object> arr:(3) [4, 5, 6]

// 或者 arr.splice(0, 3, 4, 5, 6)
// 但不能 arr = arr.splice(0, 3, 4, 5, 6)

2. readonly

2.1 作用

返回一个只读的响应式对象,不能对其属性进行赋值操作

2.2 用法

let obj = reactive({name: 'lzy'})
let readObj = readonly(obj)

readObj.name = "LZY"  // 提示:无法分配到 "name" ,因为它是只读属性。

console.log(readObj.name)  // lzy
注意:readonly() 的参数(响应式对象)如果改变属性,则返回的只读对象对应的属性也会改变
let obj = reactive({name: 'lzy'})
let readObj = readonly(obj)

obj.name = "LZY"  

console.log(readObj.name)  // LZY

3. shallowReactive

3.1 作用

只实现第一层的响应式,相当于 ref 只响应到 .value

3.2 用法

<template>
    <div>{{ obj }}</div>
    <hr>
    <button @click="change">修改</button>
</template>
    
<script setup lang="ts">
import { reactive, shallowReactive } from 'vue'

let obj = shallowReactive({
    name: 'lzy',
    age: 16,
    car: {
        brand: 'Benz'
    }
})

const change = () => {
    obj.car.brand = "BMW"
    // 更改了值,但页面上的显示值不会改变,说明深层失去了响应式
    console.log(obj.car.brand)  // BMW
}
  
</script>

3.3 注意点

ref 及 shallowRef 一样,reactive 及 shallowReactive 不能写在一起,不然后者会被强制更新依赖
<template>
    <div>{{ obj }}</div>
    <hr>
    <button @click="change">修改</button>
</template>
    
<script setup lang="ts">
import { reactive, shallowReactive } from 'vue'

let obj = shallowReactive({
    name: 'lzy',
    age: 16,
    car: {
        brand: 'Benz'
    }
})

const change = () => {
    obj.name = "LZY"
    obj.car.brand = "BMW"
    // 更改了值,页面上的显示值也会改变,因为 shallowReactive 依赖被强制更新
    console.log(obj.car.brand)  // BMW
}
  
</script>