Vue3 响应式API-Reactive

482 阅读2分钟

这是我参与8月更文挑战的第2天,活动详情查看: 8月更文挑战

什么是响应式

响应性是一种允许我们以声明式的方式去适应变化的编程范例。
当一个值依附另一个值进行计算时, 如果前一个值发生了变化, 依附的那个也会同时进行变更.
典型案例参见 excel 函数. 当单元格A3=SUM(A1:A2)时, 此时更改A1或A2任意一个发生改变时, A3会立即作出响应更新.

响应式是Vue3的核心API。
官方也把此响应式API进行单独打包,即便不使用Vue3的情况下也可以独立使用:@vue/reactivity

响应式API-Reactive

Reactive 是Vue3中核心方法,是响应式API的心脏。

Vue3核心响应式方法有两种: 一个是 ref 它是对单个值创建的响应式, 另一个 reactive 它是对一个对象创建的深度响应式.

其余的一些方法都是围绕着这两种响应式进行的扩展类方法.
有关 ref 响应式的学习参见这里: Vue3 响应式API-Refs.

reactive有3个关键方法:

  • reactive()
  • isProxy()
  • isReactive()

reactive 创建响应式

传入一个对象返回对象的响应式副本

const obj = reactive({ count: 0 })

转换后的对象是一个深度响应的. 它基于ES2015 Proxy 的实现中, 返回的 proxy 是等于原始对象的。建议只使用响应式 proxy,避免依赖原始对象。

const origin = { count: 0 }
const current = reactive(origin)
console.log(origin === current) // false

reactive 将解包所有深层的 refs,同时维持 ref 的响应性。

const count = ref(1)
const obj = reactive({ count })

// ref 会被解包
console.log(obj.count === count.value) // true

// 它会更新 `obj.count`
count.value++
console.log(count.value) // 2
console.log(obj.count) // 2

// 它也会更新 `count` ref
obj.count++
console.log(obj.count) // 3
console.log(count.value) // 3

当将 ref 分配给 reactive property 时,ref 将被自动解包。

const count = ref(1)
const obj = reactive({})

obj.count = count

console.log(obj.count) // 1
console.log(obj.count === count.value) // true

isProxy 检查对象是否是Proxy对象

检查对象是否是由 reactive 或 readonly 创建的 proxy。

const obj = reactive({})
console.log(isProxy(obj)) // true

isReactive 检查对象是否是Reactive响应式对象

检查对象是否是由 reactive 创建的响应式代理。

import { reactive, isReactive } from 'vue'
export default {
  setup() {
    const state = reactive({
      name: 'John'
    })
    console.log(isReactive(state)) // -> true
  }
}

如果该代理是 readonly 创建的,但包裹了由 reactive 创建的另一个代理,它也会返回 true

import { reactive, isReactive, readonly } from 'vue'
export default {
  setup() {
    const state = reactive({
      name: 'John'
    })
    // 从普通对象创建的只读 proxy
    const plain = readonly({
      name: 'Mary'
    })
    console.log(isReactive(plain)) // -> false

    // 从响应式 proxy 创建的只读 proxy
    const stateCopy = readonly(state)
    console.log(isReactive(stateCopy)) // -> true
  }
}

文献