Vue.js: 元件 Components - Prop
16 May 2017使用元件的目的是希望互相干擾的程度愈小愈好,因此非必要儘量不要溝通。若遇到需要由父層傳遞資料給子層的時候,使用prop
即可。
Props Down
使用 Prop 傳遞資料。如下 Demo 所示,點擊「Say Hi!」按鈕會跳出訊息「Hi Peter」。
在 HTML 模版中,使用屬性「user_name」傳遞名稱(name)「Peter」給元件<prompt-component>
。由於屬性 user_name 的值是由 data 的 name 代入,需要與 Vue Instance 結合,未來在解析模版時做處理,因此加上 v-bind 屬性綁定,簡寫為:
。而在元件中,必須使用props
聲明它所獲得的資料。
程式碼。
<div id="app">
<prompt-component :user-name="name"></prompt-component>
</div>
Vue.component('prompt-component', {
template: '<button @click="sayHi(userName)">Say Hi!</button>',
delimiters: ['${', '}'],
props: ['user-name'], //使用`props`聲明它所獲得的資料
methods: {
sayHi: function(name) {
alert('Hi ' + name);
},
},
});
var vm = new Vue({
el: '#app',
delimiters: ['${', '}'],
data: {
name: 'Peter',
},
});
// 由於部落格會把使用雙花括號的內容吃掉,所以設定 delimiters 以顯示完整程式碼。
camelCase vs kebab-case
HTML 是不區分大小寫的,而 JavaScript 是嚴格區分大小寫的。因此,若非使用以 JavaScript 產生模版的方式,意即「字串模版 (String Template)」,而是使用 HTML 模版時,屬性名稱必須使用以 dash 分隔的 kebab-case 命名。
例如,在 HTML 中撰寫屬性名稱「user name」如下
(O) <prompt-component :user-name="name"></prompt-component>
(X) <prompt-component :userName="name"></prompt-component>
再次強調,這種狀況只有在 HTML 中樣版會出現,字串模版 (String Template)則無此限制。
字面量語法(Literal)vs 動態語法(Dynamic)
由於屬性 id 的值是由 data 的 id 代入,若只是經由屬性傳遞資料,模版不會做任何處理,得到的資料型態是「string」;但若使用 v-bind 屬性綁定(簡寫為:
),將來會與 Vue Instance 結合,解析模版會當成 JavaScript 表達式做計算,得到的資料型態是「number」。
如下範例,元件<prompt-component>
會代入 id,點擊按鈕後會觸發 checkID method,然後 console 目前 id 的資料型別。
Vue.component('prompt-component', {
template: '<button @click="checkID(id)">Check ID</button>',
delimiters: ['${', '}'],
props: ['id'],
methods: {
checkID: function(id) {
console.log(typeof id);
},
},
});
var vm = new Vue({
el: '#app',
delimiters: ['${', '}'],
data: {
id: 1,
},
});
Case 1:Literal
這裡的 id 的資料型態是「string」。點擊按鈕後 console 出來的結果是 string。
<prompt-component id="id"></prompt-component>
Case 2:Dynamic
這裡的 id 的資料型態是「number」。點擊按鈕後 console 出來的結果是 number。
<prompt-component :id="id"></prompt-component>
單向資料流(One-Way Data Flow)
Prop 是單向的,只會從父層傳至子層,並且 Prop 的值會隨父層更動設定而改變。若要在子層做處理,可使用「計算屬性」(Computed)自動處理或一個 Local Variable 儲存值以供使用。若 Prop 的值是陣列或物件,記得使用深拷貝(Deep Copy),避免誤觸(Call by Address)的陷阱而更改了父層 Prop 的值。
Prop 驗證(Prop Validation)
在元件中定義 Prop 的資料型態,若傳入的資料並非期望的型別,在開發模式下會報錯。
如下例,在元件中定義 id 的資料型別是數字(Number),但卻傳入字串 abc,因此報錯。
<div id="app">
<prompt-component :id="id"></prompt-component>
</div>
Vue.component('prompt-component', {
template: '<button @click="checkID(id)">Check ID</button>',
delimiters: ['${', '}'],
props: {
id: Number,
},
methods: {
checkID: function(id) {
console.log(typeof id);
},
},
});
var vm = new Vue({
el: '#app',
delimiters: ['${', '}'],
data: {
id: 'abc',
},
});
以上參考 Components — Vue.js。