昨天說到Vue的每個元件是獨立運作,但Vue設計元件的目的是為了讓每個元件都有各自的用途,然後再互相配合使用,如此一來,系統開發上也比較結構化。
只不過世事無絕對,總是會遇到這麼幾次需要將資料由外往內傳、或是由外層元件傳給內層元件的話,那要如何讓他們之間做溝通呢?以下我們來跟大家聊聊:
使用 props 傳送數據
在Vue的世界中,每個元件都是互相獨立互相不干涉的,也就是說我們不能(也不應該)在子元件中直接引用父元件的資料。
所以當父元件想要傳遞資料給子元件時,可以使用 props
屬性,將資料傳遞給子元件。
我們直接來看看昨天的 x-template
實際範例
<div id="app">
<card-components :food="item" v-for="(item, key) in list" :key="key"></card-components>
</div><script type="text/x-template" id="cardElement">
<div class="card my-5">
<div class="card-body">
<p class="card-text">{{food.name}}</p>
</div>
</div>
</script>Vue.component('card-components', {
props:['food'],
template: '#cardElement',
});
var app = new Vue({
el: '#app',
data: {
list: [
{
id: 'a',
name: '晚餐吃鐵板燒'
},
{
id: 'b',
name: '午餐吃陽春麵'
},
{
id: 'c',
name: '早餐吃火腿蛋吐司'
}
]
}
});
用個簡單的圖例跟大家說明一下資料從上層(Root)到下層(子元件)的資料流:
- data裡面的
list陣列
將資料傳給HTML中的v-for迴圈
- 因為
Vue.component
內的資料和new Vue
是分開的,HTML中的<card-components>
透過list陣列
產生3個元件, 但裡面並沒有資料,此時我們定義props:['food']
,它會去接收寫在data裡面的list陣列
- 藉由
v-bind
將food
收到的資料傳入 Vue.component
接收到資料後,順利將資料傳到x-template
中,並渲染網頁畫面。
Props 功能
- 為元件中的自訂屬性。
- 它的接受值可以是陣列或物件。
- 拿來接收父元件的資料
props的型別
如果我們只是透過props
來接收模板屬性資料時,因為模板不會做任何處理,所以我們收到的資料型別為string
,假設我們要傳入數值「15」,但因為預設資料型別為string
,「+1」後會變成「151」,而不是「16」。
為了避免這種情況,我們可以在元件定義props
的資料型別,若傳入的資料並非期望的型別,在開發模式下會報錯。
Vue.component('child', {
props: {
// 直接定義屬性
propA: Number, // 使用陣列來定義多個型態
propB: [String, Number], // 數據有預設值及`Number`型別
propC: {
type: Number,
default: 100
},
// 必須要傳送的數據及`String`型別
propD: {
type: String,
required: true
},
// 陣列/物件的的預設值由function提供
propE: {
type: Object,
default: function () {
return { message: 'hello' }
}
},
}
})
物件中的規則說明如下:
- type:資料型態
- default:預設值
- validator:檢驗屬性資料是否有效
- required:該屬性是否為必要
type可以有的屬性如下:
- String
- Number
- Boolean
- Function
- Object
- Array
- Symbol
type
可以是自訂的建構式函式,使用instanceof
來檢測。
注意,因為元件會在vue instance創建之前建立好,所以在default
或validator
函數裡,不能使用data
、computed
、methods
等屬性無法使用。
今天先跟大家分享到這兒,明天繼續來聊props的其他細節唷!
你有更多的問題嗎?你有什麼建議呢?
歡迎在下方留言,或加入我的臉書粉絲頁一起討論!
【免費支持】如果你幫我拍手5下,我有機會得到內容創作的酬勞🙂