iT邦幫忙

2025 iThome 鐵人賽

DAY 5
0
Vue.js

Vue3.6 的革新:深入理解 Composition API系列 第 5

Day 5: 響應式資料 ref 和 reactive

  • 分享至 

  • xImage
  •  

Vue 3.5 基於 Proxy (代理)重新設計了響應式系統,所有在 refreactive 包裝的資料,一旦改變,就會自動觸發 DOM 更新,保持「資料驅動 UI」的原則。

在 Vue 3 中常用的響應式 API 主要是:

  • ref() => 適合單一值或希望明確控制的情境
  • reactive() => 適合物件/陣列

Vue 3 的響應式資料方法 : refreactive 是什麼


ref

定義 :
ref 會建立一個「帶有 .value 屬性」的響應式包裝,通常用於基本型別(number、string、boolean)或需要整個物件替換的情境。

特點 :

  • JavaScript 代碼中要用 xxx.value
  • template 模板中會自動解包,直接用 {{ count }} 即可。
  • 可以包裝物件或陣列,但通常用於「單一值」最佳。
<script lang="ts" setup>
import { ref } from 'vue'

const count = ref<number>(0)

function increment(): void {
  count.value++   // JS/TS 內部必須用 .value
}
</script>

<template>
  <div>
    <p>目前數字:{{ count }}</p> <!-- 模板中自動解包 -->
    <button @click="increment">+1</button>
  </div>
</template>

reactive

定義 :

reactive 會將物件或陣列轉換成 深層的 Proxy 響應式物件,可以像操作普通物件一樣存取/修改,Vue 會自動追蹤依賴。

特點 :

  • 可以直接用 state.count++ 修改,不需要 .value
  • 適合處理「多屬性的物件或陣列」狀態。
  • 會做 深層響應:內部屬性改變也會觸發更新。
<script lang="ts" setup>
import { reactive } from 'vue'

interface User {
  name: string
  age: number
}

const state = reactive({
  count: 0,
  user: {
    name: 'kuku',
    age: 30
  } as User
})

function increment(): void {
  state.count++
}
</script>

<template>
  <div>
    <p>{{ state.count }}</p>
    <p>{{ state.user.name }} ({{ state.user.age }})</p>
    <button @click="increment">+1</button>
  </div>
</template>

如何使用 refreactive


特性 ref reactive
適合情境 單一值、原始型別 (number, string, boolean) 物件、陣列
存取方式 JS/TS 內用 .value,模板中自動解包 直接存取屬性,無需 .value
是否深層響應 單一值響應;若包物件,只是淺層包裝 深層響應(內層屬性也響應)
解構問題 不會失去響應 直接解構會失去響應,需要 toRefs
型別推斷 (TS) 適合簡單型別 適合物件型別

實作簡單的反應式資料範例


在實務上,refreactive 經常搭配:

<script lang="ts" setup>
import { ref, reactive, toRefs } from 'vue'

const count = ref<number>(0)

const user = reactive({
  name: 'kuku',
  age: 30
})

// 正確解構 reactive
const { name, age } = toRefs(user)

function growUp(): void {
  age.value++
}
</script>

<template>
  <div>
    <p>Count: {{ count }}</p>
    <p>User: {{ name }} ({{ age }})</p>
    <button @click="count++">+1</button>
    <button @click="growUp">Age +1</button>
  </div>
</template>

常見小坑與最佳實務


1. 解構 reactive 物件會失去響應

const state = reactive({ a: 1, b: 2 })
const { a, b } = state  // reactive 直接解構 → 失去響應,解構後不是響應式
import { toRefs } from 'vue'
const { a, b } = toRefs(state)  // 正確做法:toRefs

2. 何時用 ref、何時用 reactive

  • 單一標量或需要覆蓋整個值時(如 count++objRef.value = {...}):ref
  • 自然以物件/ 陣列思考、需要多屬性協同時:reactive
  • 第三方不可被代理的大物件:markRaw 或保持非響應

3. Template 自動解包

在 template 中 {{ count }} 等同 count.value;但在 JS/TS 中還是要用 .value

參考資料


  1. Vue.js 官方文件 - 響應式基礎
  2. 宋玉の數位花園 - 實現一個簡易版@Vue3&reactivity

上一篇
Day 4: Composition API 概述
下一篇
Day 6: Proxy 的底層實現
系列文
Vue3.6 的革新:深入理解 Composition API6
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言