本文同步發表於斜槓女紙部落格:Day16 萬丈高樓平地起(4):元件間的溝通橋樑Props(1)
昨天說到Vue的每個元件是獨立運作,但Vue設計元件的目的是為了讓每個元件都有各自的用途,然後再互相配合使用,如此一來,系統開發上也比較結構化。
只不過世事無絕對,總是會遇到這麼幾次需要將資料由外往內傳、或是由外層元件傳給內層元件的話,那要如何讓他們之間做溝通呢?以下我們來跟大家聊聊:
在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)到下層(子元件)的資料流:
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
來接收模板屬性資料時,因為模板不會做任何處理,所以我們收到的資料型別為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
可以是自訂的建構式函式,使用instanceof
來檢測。
注意,因為元件會在vue instance創建之前建立好,所以在default
或validator
函數裡,不能使用data
、computed
、methods
等屬性無法使用。
今天先跟大家分享到這兒,明天繼續來聊props的其他細節唷!
參考資料