[前端史萊姆與Vue的三十天時光冒險]Day17 萬丈高樓平地起(5):元件間的溝通橋樑Props(2)

Mio
斜槓女紙
Published in
Oct 2, 2019

不正確溝通,網頁畫面就不理你喲!

嗨!承接昨天的內容,今天要繼續和大家聊props的一些眉眉角角,廢話不多說,直接開始囉!

props的命名

Vue組件命名方式有三種,如果以card component為範例的話,這三種的寫法如下

  • kebab-case(串燒):card-component (單字與單字間使用連接符號)
  • camelCase(小駝峰式命名):cardComponent (第一個單字以小寫字母開始;第二個單字的首字母大寫)
  • PascaleCase(大駝峰式命名):CardComponent (每一個單字的首字母都採用大寫字母)

在HTML中,屬性是不區分大小寫的,也就是說如果你在HTML中寫myattribute跟寫myAttribute,HTML會看成是一樣的東西,所以如果我們在元件中使用props去接收屬性的資料時,寫的是camelCase(駝峰式命名法)的屬性名稱,在HTML中就要自動轉換為kebab-case(用dash間隔的命名法)。

實際範例

//HTML
<div id="app">
<!-- 顯示:我是 -->
<name-card myName="鍾小呆"></name-card>

<!-- 顯示:我是 鍾小呆 -->
<name-card my-name="鍾小呆"></name-card>
</div>
//JS
Vue.component('name-card', {
props: ['myName'],
template: '<p>我是 {{ myName }}</p>'
})
var vm = new Vue ({
el: '#app'
})

Props 使用上的注意事項

單向數據流(One-Way Data Flow)

經由props屬性傳遞的資料是單向綁定的,也就是當父元件屬性資料改變時,只能單向傳遞資料給子元件,反過來是不行的,目的是為了不讓子元件可以任意去更改父元件的狀態。

當父元件更新時,子元件的所有prop也會跟著更新為最新的資料。如果遇到需要更改父元件的資料狀態時,我們可以另外宣告一個變量來記錄。

直接看看實際範例,若我們想直接從input修改文字內容的話,console會產生警告訊息

若想解決這個問題的話,我們可以採用data(區域變數)這個方法來接外部傳進來的內容:

//HTML
<input type="text" class="form-control mt-3" v-model="newWord">
//JS
Vue.component('message', {
props: ['word'],
template: '#box',
//區域變數data
data: function () {
return {
newWord: this.word
}
},
});

改寫後,兩段資料的內容就被區別開來,console也不會出現錯誤訊息囉!

AJAX 延遲 及 物件傳參考特性

直接來看 實際範例

假設我們的資料是經由ajax的方法傳入的話,Vue會先在Root中宣告一個user物件,然後透過 AJAX 行為把遠端的資料抓進來之後,才把它存進user物件裡面,在這之中會有時間差(因為執行的東西會先放在 event queue),所以card元件會報錯說找不到資料:

//HTML
<div id="app">
<div class="row">
<div class="col-sm-4">
<card :user-data="user"></card>
</div>
</div>
</div>
<script type="text/x-template" id="card">
<div class="card">
<img class="card-img-top" :src="user.picture.large" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">{{ user.name.first }} {{ user.name.last }}</h5>
<p class="card-text">{{ user.email }}</p>
</div>
<div class="card-footer">
<input type="email" class="form-control" v-model="user.email">
</div>
</div>
</script>
//JS
Vue.component('card', {
props: ['userData'],
template: '#card',
data: function() {
return {
user: this.userData
}
}
});
var app = new Vue({
el: '#app',
data: {
user: {},
},
created: function() {
var vm = this;
$.ajax({
url: 'https://randomuser.me/api/',
dataType: 'json',
success: function(data) {
vm.user = data.results[0];
}
});
}
});

此時我們可以採用v-if的方式,假設 user 某個特性並沒有完全讀進來之前,就不要把這個卡片執行出來:

// 假設有email就把資料繪製出來
<card :user-data="user" v-if="user.email"></card>

實際出來的結果如下圖:

今天就先和大家分享到這兒,明天我們再繼續唷!

你有更多的問題嗎?你有什麼建議呢?
歡迎在下方留言,或加入我的臉書粉絲頁一起討論!

【免費支持】如果你幫我拍手5下,我有機會得到內容創作的酬勞🙂

--

--

Mio
斜槓女紙

每天努力克服拖延症,致力於斜槓人生。