Andy's blog

If you always do what you've always done, you'll always get what you've always got.

0%

Vue Component(元件)-props使用注意細項(2)

參考資料


狀況一:讀取遠端資料

我們今天如果使用AJAX讀取遠端資料時,並透過props將資料傳入子元件時,有可能在畫面上無法正常顯示(如下圖)。而這個原因就是AJAX非同步特性,造成遠端回傳資料尚未載入,而使畫面一片空白。
https://ithelp.ithome.com.tw/upload/images/20191004/20114645pD3pABOF0K.png

這時,我們該如何解決呢?
我們可以透過簡單v-if來判斷,當資料完全載入時,在呈現於畫面上就可以瞜。

寫法如下:

範例連結

1
2
3
4
5
6
7
8
9
<div id="app">
<div class="row">
<div class="col-sm-4">
<!-- 這邊主要因為AJAX時間差,造成卡片載入錯誤。我們只要使用v-if成功載入時再渲染就不會跳錯 -->
<card :user-data="user" v-if="user.gender"></card>
</div>
</div>
</div>


狀況二:非Prop的特性(Non-Prop Attributes)

說明:一個非prop 特性是指傳向一個組件,但是該組件並沒有相對應prop定義的特性。

我自己的理解如下(如果有錯,再請大家糾正)
如下範例:假設今天我們在元件上要放置一張圖片,而我們在template中並沒撰寫圖片的heightwidthalt屬性,這時Vue允許我們可以直接將這些特性撰寫在HTML上,如此一來這些特性就會被放置在元件實體內。(感覺有點像data-* ,自定義屬性方法)

例子如下:練習連結
HTML部分

1
2
3
4
5
6
7
<div id="app">
<h2>Default</h2>
<nicolas-cage alt="hello"></nicolas-cage>
<p>
<h2>H/W</h2>
<nicolas-cage width="199" height="199"></nicolas-cage>
</div>

JavaScript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Vue.component('nicolas-cage', {
template:'<img :src="url" />', //取得computed中url結果
data() {
return {
}
},
computed:{
url:function() {
let theUrl = 'https://fakeimg.pl/'+this.width+'/'+this.height;
return theUrl;
}
},
props:{
height:{
default:400,
},
width:{
default:400
}
}
});

var app = new Vue({
el: '#app',
data() {
return {
}
}
});

說明:可以注意到元件的template中並沒有用mustache語法來綁定外部傳進來資料。

替換/合併已有的特性

我們上面提到,如果在元件template上並沒有相對應props屬性,但我們卻在HTML template上直接撰寫attribute,Vue會讓這些attribute直接寫入元件實體中。
範例
<bootstrap-date-input>的模板內容

1
<input type="date" class="form-control">

HTML上模板

1
2
3
4
<bootstrap-date-input
data-date-picker="activated"
class="date-picker-theme-dark"
></bootstrap-date-input>

最終顯示結果
form-control,這是在組件的模板內設置好的
date-picker-theme-dark,這是從組件的父級傳入的
https://ithelp.ithome.com.tw/upload/images/20191004/20114645EKBnma38qa.png

禁用特性繼承

剛有提到,因為非Prop的特性,即使我們在元件中並沒有使用props來定義型態或接受資料,Vue仍然會把在HTML上撰寫的特性放置於元件實體中。而今天如果我們不想要繼承元件內實體屬性,我們可以這樣做~
範例如下:

1
2
3
4
Vue.component('my-component', {
inheritAttrs: false,
// ...
})

而我們也因為可以設定inheritAttrs: false$attrs緣故,可以自行決定哪些attribute要放置到哪個元素中。像是下方範例,我們透過v-bind="$attrs",將元件內實體屬性放置在input中。
範例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Vue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
template: `
<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
</label>
`
})

後記

在撰寫非Prop的特性(Non-Prop Attributes)時,因為我是第一次接觸這個特性,撰寫起來有點卡卡的,也不太確定是否理解正確(哈哈)。我其實對於實務上會用在哪些地方,其實我也蠻好奇的,若有前願意分享也歡迎下方留言,那我們就明天見啦~