上一篇我們提到,要從根實例傳資料到元件裡,需要使用 props
特性來傳遞,今天這篇筆記會談談 props
如何實際使用。
在 HTML 放入元件
1 | <div id="app"> |
定義元件模板
1 | <script type="text/x-template" id="photo"> |
宣告 Vue 根實例
1 | var app = new Vue({ |
在 Vue 根實例上方宣告一個元件
1 | Vue.component('自定義元件名稱',{ |
接下來傳遞資料的方式可以選擇靜態傳遞或動態傳遞。
靜態與動態傳入數值差異
加在 HTML 標籤上的屬性可以分為靜態跟動態兩種,沒有設定 v-bind
的屬性為靜態,有設定 v-bind
的屬性為動態。
靜態屬性的值一律會轉為字串型別,動態屬性的值則不一定是字串。
靜態傳遞
<photo img-url="圖片的網址"></photo>
原本在元件內的 props
值為 imgUrl
,放到 HTML 中時要把駝峰改成 -
。img-url
的值(圖片網址)會透過 x-template
中 :src="imgUrl"
而跑到元件 props
裡。
動態傳遞
<photo :img-url="url"></photo>
這裡的 url
作為與元件 props
imgUrl
綁定的值,同時代表的是根實例 data
物件中的 url
特性,因此會把 url
中的圖片網址帶進 props
裡面。
props 圖解
props 使用注意事項
1. 單向數據流
像上面這樣使用 v-bind
綁定 props
,並傳入 Vue 實例的 data
資料,如果又在 DOM 運用 props
屬性建立 v-model
會形成一個問題,就是當使用者從畫面上修改資料時,會去動到根實例的 data
,但這樣是不合規範的,所以會跳錯。
解決辦法是在元件中新增 data
特性,對應一個 function,並在裡面 return
新的特性,當作與畫面雙向綁定的標的,這樣就不會跳錯了。
1 | // JS |
newUrl
的值有兩個角色,第一個是接收 props
傳入的資料,第二個是放在元件模板中設定 v-model
,使用 newUrl
來與畫面做雙向綁定,就能把 props
資料與 Vue 實例的 data
做隔離。
2. 尚未宣告的變數
當我們在根實例 data
物件新增空的物件,並希望透過 AJAX 推資料進去這個空物件時,元件渲染會發生在 AJAX 資料推進來之前,就會造成抓不到資料而跳錯。
解決方法是使用 v-if="AJAX 傳入的資料特性"
,確保 AJAX 取得資料後,才渲染元件;在資料尚未取得前,元件都不會顯示。
範例:<card :user-data="user" v-if="user.phone"></card>
v-if
裡對應的值可以是 AJAX 資料中隨便一個資料特性,這邊的 user
指的是一開始就宣告的空物件名稱。
3. 物件透過參考的方式傳遞資料
在 JavaScript 中,當我們宣告一個變數並賦予它一個新的物件時,記憶體的某處也會建立起一個物件,然後把剛剛的變數指向新生成的物件。
接著,如果我們又宣告第二個變數,並將這個變數指向第一個變數的話,當我們更新第一個變數裡的特性值,第二個變數的內容也會隨之更新。
也就是說,兩個變數都是指向同一個實體。
所以,當我們在畫面上修改資料,會更改到 props
的值,甚至連 Vue 實例的 data
物件也會跟著被改變。
那為何單向數據流無法像這樣傳遞呢?因為單向數據流傳遞的是一般字串,所以無法像物件這樣傳遞參考的特性。如果沒有修改物件的特性,都還是維持單向數據流的概念。
4. 維持狀態與生命週期
如果不希望元件每次都重新生成,或是元件內的內容是由 AJAX 而來,而你不希望每次重整,元件都接收到不一樣的內容的話,就可以使用 <keep-alive>
標籤包住元件,這樣就能維持元件的狀態了。
props 值的型別
預先定義 props
應該傳入哪種型別的資料,避免傳入錯誤的資料。
1 | // 原本是這樣寫 |
有時候 props
不會接收到來自外部的值,但如果我們希望它帶有預設值,可以這樣做:
1 | props: { |