前面介紹過
接下來要介紹 樣板(template),用於呈現資料。
Vue.js 05 - 資料綁定(data binding) 與 樣板(template) 語法 已介紹如何綁定資料與樣板。
這篇打算講解已寫好的樣板,如何加入組件/元件(component)
宣告。
第一種,組字串
Vue.component('child', {
template: '<ul><li v-for="item in list">{{ item.name }}</li></ul>'
/* JS字串串接 */
/*
template: [
'<ul>',
' <li v-for="item in list">{{ item.name }}</li>',
'</ul>'].join('');
*/
});
<template>
Hello.vue
<template>
<ul>
<li v-for="item in list">{{ item.name }}</li>
</ul>
</template>
Vue.component('child', {
/* 免寫,vue-loader 會幫你補上 template 屬性 */
});
Vue 1.x用,寫在html,指定<template>
名
<template id="child-template">
<ul>
<li v-for="item in list">{{ item.name }}</li>
</ul>
</template>
Vue.component('child', {
template: '#child-template'
});
Vue 2.x用,寫在<script>
的x-template,指定其名
<script type="text/x-template" id="child-template">
<p>Hello hello hello</p>
</script>
Vue.component('child', {
template: '#child-template'
});
不好看,但網路發問用得到。
一開始做component
時,想得沒那麼多,需求很簡單。
<app></app>
<template>
<div>
<!-- 最初的樣板定義 -->
</div>
</template>
<script>
export default {
/* ... */
}
</script>
後來需求逐漸增加,神說<app>
有了<header>
和<footer>
,我們就得生給他,App.vue變成
<template>
<div>
<!-- 最初的樣板定義 -->
<app-header></app-header>
<app-footer></app-footer>
</div>
</template>
<script>
export default {
/* ... */
components: {
AppHeader,
AppFooter
},
/* ... */
}
</script>
組件內容未必固定,若是我們兩個版本的<app>
都要?
為了少部分的差異,多做一個組件,有點脫褲子放屁。
要怎麼讓組件樣板具有彈性呢?
像是這樣
<app>
<app-header></app-header>
<app-footer></app-footer>
</app>
<slot>
ng1 有 transclude,Vue 給你 <slot>
<template>
<div>
<!-- 最初的樣板定義 -->
<!-- <app>樣板留下插座,供動態插入 -->
<slot></slot>
</div>
</template>
<app>
<!-- 如此一來,只要接上插座 -->
<!-- <app>元素內的html會插入<slot>的位置 -->
<app-header></app-header>
<app-footer></app-footer>
</app>
有時插入內容想放在不同位置,給它個名字 - 具名<slot>
<template>
<div class="modal fade">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<slot name="modal-header">
</div>
<div class="modal-body">
<slot name="modal-body">
</div>
<div class="modal-footer">
<slot name="modal-footer">
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</template>
<modal>
<h4 slot="modal-header" class="modal-title">Modal title</h4>
<p slot="modal-body">One fine body…</p>
<button slot="modal-footer" type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button slot="modal-footer" type="button" class="btn btn-primary">Save changes</button>
</modal>
<app>
組件,把省下的merge時間拿去泡咖啡。同樣寫法,但這種作法會完全覆蓋掉<app>
原始內容
<app inline-template>
<div>
<p>These are compiled as the component's own template.</p>
<p>Not parent's transclusion content.</p>
</div>
</app>
等校於
<!-- <app>模板原始內容不見了 -->
<div>
<p>These are compiled as the component's own template.</p>
<p>Not parent's transclusion content.</p>
</div>