本文同步發表於斜槓女紙部落格:Day17 萬丈高樓平地起(5):元件間的溝通橋樑Props(2)
嗨!承接昨天的內容,今天要繼續和大家聊props的一些眉眉角角,廢話不多說,直接開始囉!
Vue組件命名方式有三種,如果以card component為範例的話,這三種的寫法如下
在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屬性傳遞的資料是單向綁定的,也就是當父元件屬性資料改變時,只能單向傳遞資料給子元件,反過來是不行的,目的是為了不讓子元件可以任意去更改父元件的狀態。
當父元件更新時,子元件的所有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的方法傳入的話,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>
實際出來的結果如下圖:
今天就先和大家分享到這兒,明天我們再繼續唷!