Vue 初心者筆記 #17 Props – 由外到內的資料傳遞

本篇文章介紹父子元件之間,由外到內的資料傳遞方式 Props。

Props 基本介紹

Props 是由外層到內層的資料傳遞,分為「靜態傳遞」與「動態傳遞」。

靜態傳遞

直接透過 props 把資料傳進來。

動態傳遞

如果外部資料是即時變動的,我們會使用 v-bind 的方式 (:img-url) 綁定外層的動態資料。

下方例子中,整個 Vue 應用程式(外層)有一份資料叫做 url,我們要把它傳到內層的 img-url 裡面做使用。
(這個內層的 img-url 就是 props 定義的 imgUrl

等價命名 (camelCase vs. kebab-case)

因為 HTML 的「特性名」是大小寫不敏感的,瀏覽器會把所有大寫字符解釋為小寫字符,因此這裡遇到大寫時要換成 dash (-) 符號。

因此,camelCase(小駝峰命名)與 kebab-case(短橫線分隔命名)是等價的。

Props 注意事項

單向數據流

下方範例中,如果修改 <input> 標籤裡的值,會因為 Vue 無法更改 props 從外層傳進來的值的緣故,而跳出錯誤訊息。

這個就是 props「單向數據流」的概念。
Vue 希望 props 傳進來的資料盡量維持單向,而不要反向地寫回去。

因此,要避免這個錯誤,我們可以另外新建一個 data,來接收 props 從外部傳進來的資料內容。

我們定義一個新的變數 newUrl 來接 props 從外部傳進來的資料,
避免 imgUrl 直接與外層的資料(圖片網址 url)進行綁定。

imgUrl 換成 newUrl,多一層的概念。

這時候,我們再來調整這個變數就不會有問題囉!

尚未宣告的變數

有時候,我們的資料匯入會有一些時間差,導致 Vue 出現抓不到值的錯誤。

imgur

這時候我們可以使用 v-if 讓元件的產生時間往後移,讓資料完成時才同步繪製元件!

範例程式碼:

問題:變數還沒傳進去,導致元件跳錯。
解法:如果有電話號碼,才繪製出卡片。

在這個例子中,我們透過 AJAX 抓取遠端的資料後,存進宣告的變數 user 裡面,再將這些圖片顯示出來。

但是因為 user 在做這些傳入的動作時會有時間差,所以會出現找不到變數的錯誤。

因此我們使用 v-if,假設 user 裡面的某個特性還沒載入,就先不要執行渲染至畫面的動作。

選取一個一定會有的特性,像是這裡就選擇用電話號碼 phone

物件傳參考的特性

如果我們在畫面上修改 card user 裡面的 email,可以發現 Root useremail 也會改變,這是因為「物件」會傳遞「參考值」的特性。

我們可以透過下面這個例子來理解。

1
2
3
4
5
var a = { user: '小明' };
var b = a;
b.user = '小強';

console.log(a.user); // 小強

範例中,我們將 buser 改為 '小強',結果 auser 也會變成 '小強'

這是因為 a 物件在傳遞的時候,是把整個參考值傳遞到 b 上面,所以這時候如果 b 修改,a 也會被修改。

因此,我們在修改 email 的值的時候,外層的 email 的值也會被修改。

維持狀態與生命週期

下面這個例子裡的 <keep-card> 元件,可以透過 Checkbox 的勾選來重新生成。每次勾選 Checkbox,都會讓元件銷毀再生成,即重新執行 AJAX。

如果這是我們想要的結果,那沒問題!

但是如果不希望每次元件生成時,都重新執行一次裡面的程式碼的話,
我們可以給它加上 <keep-alive> 標籤,並把 v-ifdiv 移到卡片上面。

此外,這邊也有剛才提到的時間差問題(AJAX 還沒執行完成,資料還沒有載入好),
所以我們加上 v-if 確保資料載入後才讀出資料內容。

取消勾選後,從 Vue DevTools 可以看到 <KeepCard> 會變成 inactive(暫時隱藏)的狀態。

imgur

下次啟動時,就不會重新執行元件的整個生命週期,而是會直接把它呼叫出來囉!

Props 型別與預設值

型別

props 傳遞外層資料到內層時,如果要顯示數值資料,可以直接設定 props 的資料型別 (type),
同時外層的 data 也要以純數值 (Number) 傳遞,不要寫成 String。

預設值

有時候製作元件時,希望它能帶有預設值,可以直接於 props 裡設定 default 屬性。

靜態與動態傳入數值的差異

在使用 HTML 屬性傳入資料內容時,有分為靜態屬性與動態屬性。

以範例中的 HTML 屬性 money 為例:
數值於靜態屬性 money 傳入時會是「字串」,
若加上冒號 :money,改為動態傳入時,這時候的數值就會是「數值」。

以上資源是我自己整理過後的筆記,若有錯誤歡迎隨時和我聯繫。