iT邦幫忙

2025 iThome 鐵人賽

DAY 4
3
Vue.js

在 Vue 過氣前要學的三十件事系列 第 4 篇

在 Vue 過氣前要學的第四件事 - 2025 了還要用 .value ?

  • 分享至 

  • xImage
  •  

前言

在 Vue 的使用中你可能會看到 ref 跟 reactive,
這是 Composition API 的核心,讓資料具備響應式。

但平平都是用來做變數的引用,到底差在哪裡確實是會讓人有點懷疑,
此篇文章就是用來釐清何種情況使用為較優解。

[2026/02/10 更新]
關於文中一些可能導致誤解的觀念將會並補充正確觀念

基礎語法

為避免第一次使用 Vue 的人看不懂
這邊還是簡單講解一下怎麼看響應式函數
https://ithelp.ithome.com.tw/upload/images/20250903/20172784yRJw0o1Xdi.png

註解

  1. 宣告一個常數,可以讓我們後續使用。
  2. 為這個常數賦予名稱。
  3. 響應式函數並接收一個參數初始值。
  4. 初始值為數字 0。

所以上面這句可以被理解為:
我們宣告了一個常數叫做 count,它是一個響應式的物件,裡面存了一個初始值 0。

言傳不如身教,話不多說,直接上手開始練習吧。

使用

ref

<script setup>
import { ref } from 'vue'

const year = ref(2025)

console.log(year.value) // 2025
</script>

<template>
	<h1>{{ year }}</h1>
</template>

reactive

<script setup>
import { reactive } from 'vue'

const date = reactive({year:2025})

console.log(date.year)  // Proxy(Object) {year: 2025}
</script>

<template>
	<h1>{{ date.year }}</h1>
</template>

一定要用 ref 或 reactive 嗎?

先說結論,如果你要 資料響應式變化 那就要用。

當你在模板中使用了一個 ref,然後改變了這個 ref 的值時,Vue 會自動檢測到這個變化,
並且相應地更新 DOM。
這是通過一個基於依賴追蹤的響應式系統實現的。
當一個組件首次渲染時,Vue 會追蹤在渲染過程中使用的每一個 ref。
然後,當一個 ref 被修改時,它會觸發追蹤它的組件的一次重新渲染。 - 為什麼要使用 ref?

使用時有什麼差異? 兩者接收的資料型態差在哪?

在使用上單一值會使用 ref ,而遇到物件時用 reactive 會更好,
但是! 其實你全都用 ref 也無所謂,後面會講為什麼。

ref 可以接受任意資料型態包含物件,
但通常會使用基本資料類型 ( Primitive data types )
reactive 只能接受物件類型 ( Reference data types )

[2026/02/10 更新]
這邊補充一下 官方雖然推薦全用 ref 也無所謂,
但最後還是會補充一下不同情境下可以考慮用 reactive

所以到底為甚麼要 .value ?


我相信不管是第一次使用 Vue 或是使用一陣子的朋友都會覺得這個 .value ,
是一個很討厭的東西,都 2025 了要引用變數居然還要 .value 。

簡單來說就是由於原生 JavaScript 的限制,
我們需要透過 value 讓 Vue 有一個機會追蹤物件屬性變更,

但在這篇我們還不會過多講解這件事,
在後面響應式核心篇會再深入講解,讓我們銜接到 Alien-signals 時可以有更好的了解。

為什麼在 <template> 使用無須 .value?

Vue 會自動解包 模板中的響應式物件:

注意,在模板中使用 ref 時,我們不需要附加 .value。
為了方便起見,當在模板中使用時,ref 會自動解包 - ref()

reactive 就這麼沒人要嗎?

https://ithelp.ithome.com.tw/upload/images/20250903/20172784DgFrfeL6Nn.jpg
確實 ref 就足以應付大部分的場景,不過這邊我們可以來看一段 code。

<script setup>
import { ref } from 'vue';

const article = ref({
  author: 'Yanya',
  version: '3.5.0',
  title: 'Progressive JavaScript Framework'
})

function updateVersion(){
  article.value.version = '3.6.0'
}
</script>

<template>
  <h1>{{article.title}}</h1>  
  <h2>Author : {{article.author}}</h2>  
  <p>version : {{article.version}}</p>
  <button @click="updateVersion">點我更新版本</button>
</template>

這邊可以看到如果我用 ref 的話我就要 article.value.version 才有辦法更新裡面的屬性,
老實說真的有點煩。

於是我們稍微調整一下

+const article = reactive({
-const article = ref({
  author: 'Yanya',
  version: '3.5.0',
  title: 'Progressive JavaScript Framework'
})

function updateVersion(){
+   article.value.version = '3.6.0'
-   article.version = '3.6.0'
}

確實阿,會乾淨一點,那如果我今天多加一個狀況,我的物件裡面有 35 個屬性呢?

const article = reactive({
  author: 'Yanya',
  version: '3.5.0',
  title: 'Progressive JavaScript Framework'
+  // 略...
})

function updateVersion(){
  article.version = '3.6.0';
+  article.author = 'Evan';
+  article.title = 'Ref vs Reactive';
+  // 略...
}

聰明的你可能會想說,那不然我直接賦予他新的物件

不能替換整個對象:由於 Vue 的響應式跟蹤是通過屬性訪問實現的,因此我們必須始終保持對響應式對象的相同引用。這意味著我們不能輕易地“替換”響應式對象,因為這樣的話與第一個引用的響應性連接將丟失 - reactive() 的局限性

那我要怎麼做 QQ

這邊的話我們可以善用 Object.assign 將淺層物件複製到目標物件上

const article = reactive({
  author: 'Yanya',
  version: '3.5.0',
  title: 'Progressive JavaScript Framework'
  // 略...
})
+ const newInfo ={version:'3.6.0', author:'Evan', title:'Ref vs Reactive'}

function updateVersion(){
-  article.version = '3.6.0';
-  article.author = 'Evan';
-  article.title = 'Ref vs Reactive';
+  Object.assign(article,newInfo)
}


[2026/02/10 更新]
各位應該也可以發現 reactive 無法輕易替換整個對象的原因就是他不是這樣設計的,
reactive 是用來做深度 proxy 的狀態物件,讓你可以修改裡面單一欄位內容或資料結構
如果要替換整個物件,建議用 ref

延伸閱讀

useTemplateRef() 3.5+

https://ithelp.ithome.com.tw/upload/images/20250903/20172784XfBUq8iyxC.png
如果我們今天需要用一個響應式物件跟模板連接,
為了避免和一般 ref 搞混,可能會嘗試在名稱上加上一個 Ref,
用來表示這不是 Primitive Data,而是 Instance 或 HTMLElement,例如 xxRef = ref('') 。

然後模板區域使用它,還要 ref="inputRef",這樣有點繞遠路的感覺。

在 3.5 時推出了 useTemplateRef(),主要是我們可以傳入自定義名稱,
然後模板區域直接 ref="input" 。

就我自己個人來講, 我會把需要綁定模板去做一些操作, 例如 .show .on ,
那我就會使用 useTemplateRef + InstanceType,這樣很好的展示出跟原始數據型態的 ref 差異

推薦使用時機 :
當你想要自定義 template ref 的名稱時可以使用

結語

今天我們正式進入響應式系統篇章,為了打好基礎,響應式篇章會花比較大的篇幅做講解,
也透過了實際使用來了解 ref 和 reactive 的語法差異。

講解為什麼官方推薦使用 ref() 作為聲明響應式變數的 API,
經由實際案例來了解 reactive 的限制與優勢,
補充了 useTemplateRef 的使用方法。

可以看到官方所說的 reactive 的限制較多,包含傳入的值有限類型,
不能輕易替換物件值,解構將會失去響應式

由於這些限制,我們建議使用 ref() 作為聲明響應式狀態的主要 API。

所以結論就是使用 ref 作為響應式變數的引用在大多情況是較好的解, 除非你要深層的監聽物件內部屬性, 或是把多個相依賴的 ref 組合成一個物件, 那就可以考慮用 reactive

[2026/02/10 更新]
關於這個結論是比較粗淺的解釋,這邊先感謝 Astolfo 福大幫我釐清了很多觀念
首先是關於 ref 跟 reactive 各自的使用情境

//-----------------
// ref
//-----------------
const name = ref<string>(''); // 單一值
const user = ref<User>(); // 整個物件會被替換
const state = ref<State>({ type: 'idle' }); // 狀態模型

//-----------------
// reactive
//-----------------

const form = reactive({ name: '', address: '' }); // 一組相關的資料且不應該被整個換掉
form.name = 'John'; 

const staff = reactive({ /* 宣告資料結構 */
  profile: {
    username: 'john',
    address: { city: 'Taipei' }
  },
  roles: ['admin', 'user']
}); 

staff.profile.username = 'jane'; // 修改巢狀屬性

看過上面這些範例,可以再來補充一下,因為 ref 是採深層遞迴,且遇到物件
就會轉 reactive 並變成 proxy 物件那如果裡面超級多層有夠大包又深,
那每層都要包 proxy ,就會造成效能損耗,因為裡面每個變動都會更新響應式物件
如果是這種大物件,可以考慮用 shallowRef() 控制邊界進行淺層響應

總而言之 ref 跟 reactive 都有各自被設計出來的理由,雖然官方推薦先用 ref
但還是可以根據不同狀況下去思考要用哪種 API

如果你喜歡這個系列或是想看我發瘋,歡迎按下 訂閱 一起走完這三十天吧。

一些小練習

  1. ref 跟 reactive 接受的值類型有什麼差別?
  2. 如果今天我的值是靜態的從頭到尾都不會變, 我還要無腦套 ref 嗎?
  3. 在大多情況下通常會選擇用 ref 還是 reactive? 為什麼?
  4. templateRef 和 ref 使用差異在哪? 為什麼要特地出這個 API?

資料來源

  1. Vue 官方文件

https://ithelp.ithome.com.tw/upload/images/20250904/20172784YIsuOy2HHh.png


上一篇
在 Vue 過氣前要學的第三件事 - Rolldown 上位後會對 Vite 產生什麼影響
下一篇
在 Vue 過氣前要學的第五件事 - 主動還是被動
系列文
在 Vue 過氣前要學的三十件事 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

1
Tim Lin
iT邦新手 5 級 ‧ 2025-09-16 12:00:15

以前剛接觸 Vue3 的時候也覺得 .value 很煩人...
不過後來發現 .value 可以很好的和一般狀態區分,知道目前是在存取響應式狀態還是一般狀態 ~
所以我比較支持全部使用 ref XD

另外~ ref 也是預設深層監聽物件內部屬性的唷 !

Yanya iT邦新手 4 級 ‧ 2025-09-16 12:22:35 檢舉

感謝回覆! 我個人也是覺得各有各的好處
沒錯~ ref 也是有支援深層監聽的!

在 Vue 過氣前要學的第六件事 - 響應式到底為什麼那麼重要 中,
也有一小段篇幅是在講解 ref 原始碼內部是怎麼處理的!

歡迎對這部分有興趣的朋友可以前往文章看看我怎麼發瘋哈哈

Tim Lin iT邦新手 5 級 ‧ 2025-09-16 13:44:02 檢舉

梗圖很有料XD 我反而比較好奇哪來這麼多素材 (重點誤

Yanya iT邦新手 4 級 ‧ 2025-09-16 14:32:12 檢舉

蠻多 gif 都是來自 7tv
至於其他的都是活網仔的經驗 XDD

我要留言

立即登入留言