ref() 響應小學堂

Vue3 提供了 ref() 跟 reactive() 兩種可供資料與畫面響應的資料類型,當程式或 API 傳來的資料改變時,畫面上的資料也會隨之改變。Vue3 的官方文件尤其推薦用戶使用 ref() 來宣告響應資料。以下整理幾個使用 ref() 時會迷惑的問題與解答,你可以 copy 下方的程式碼,到官方提供的 playground 玩玩看。

Vue 官方 playground

Q: ref()能夠接受的資料類型為何?

A: 不同於 reactive() 只能接受物件、陣列與collection類型資料。ref()能夠放入字串、數字、布林值、物件、陣列或 Map 等集合式資料。

Q: ref() 是否為深層響應?

A: ref() 為深層響應,下例中即使嵌套多層物件, ref() 仍然能維持資料與畫面的響應。

<script setup>
import { ref } from 'vue'
const msg=ref({a:'1',b:{c:{d:{e:'hello'}}}})
console.log(msg === myGrandSon) 
// true
</script>

<template>
  <h1>{{ msg.b.c.d.e }}</h1>  
  <input v-model="msg.b.c.d.e" />
</template>

Q: ref() 被賦予給其他的變數,是否會丟失響應性?

A: ref() 並不會因為被賦予給其他變數,就丟掉了響應性,如同下面的例子,即使 msg 被賦予給 mySon,mySon 再被賦予給 myGrandSon ,包在裡面的物件仍然指向與 msg 相同的 reference,維持資料與畫面的響應。

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

let msg = ref({a:'1',b:{c:'x'}})

const mySon = msg
const myGrandSon = mySon
</script>

<template>

  <input v-model="myGrandSon.b.c" />

  <h3>{{myGrandSon.b.c}}</h3>
  <h3>{{msg.b.c}}</h3>
</template>

Q: 物件的嵌套內放入 ref(),是否還會維持響應?

A: 下面範例中,object 的 id 屬性是一個 ref(),被包在物件中,成為物件屬性會失去了響應性。ref() 必須是頂層屬性,要在物件的最外層才有響應。

<script setup>
import { ref } from 'vue'
const count = ref(0)
const object = { id: ref(1) }
</script>

<template>
  {{ count + 1 }}  
  <!-- 1 -->
  {{ object.id + 1 }}
  <!-- [object Object]1 -->
</template>
  • 遇到上面情形要使用解構,如此 id 就能維持響應性。
const { id } = object
{{ id + 1 }}
  • 第二個方法是加上 .value:嵌在物件中作為屬性的 ref() 不會自動解包(unwrapped),如下加上.value就可以維持響應性。例如object.id.value 就可以解包,如此就能維持響應。
<template>      
  {{ object.id.value+1 }}
</template>

Leave a Reply

Your email address will not be published. Required fields are marked *