Vue.js: 元件 Components - Prop

使用元件的目的是希望互相干擾的程度愈小愈好,因此非必要儘量不要溝通。若遇到需要由父層傳遞資料給子層的時候,使用prop即可。

Props Down

使用 Prop 傳遞資料。如下 Demo 所示,點擊「Say Hi!」按鈕會跳出訊息「Hi Peter」。

Vue.js: 元件 Components - Prop

在 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'
  }
});

Vue.js: 元件 Components - Prop 驗證

以上參考 Components — Vue.js


comments powered by Disqus