什麼是組件?html
組件(Component)是 Vue.js 最強大的功能之一。組件能夠擴展 HTML 元素,封裝可重用的代碼。在較高層面上,組件是自定義元素,Vue.js 的編譯器爲它添加特殊功能。在有些狀況下,組件也能夠是原生 HTML 元素的形式,以 is 特性擴展。vue
使用組件java
註冊node
以前說過,咱們能夠用 Vue.extend() 建立一個組件構造器:webpack
1
2
3
|
var
MyComponent = Vue.extend({
// 選項...
})
|
要把這個構造器用做組件,須要用 `Vue.component(tag, constructor)` **註冊** : web
1
2
|
// 全局註冊組件,tag 爲 my-component
Vue.component(
'my-component'
, MyComponent)
|
<p class="tip">對於自定義標籤名字,Vue.js 不強制要求遵循 W3C 規則(小寫,而且包含一個短槓),儘管遵循這個規則比較好。ajax
組件在註冊以後,即可以在父實例的模塊中以自定義元素 <my-component> 的形式使用。要確保在初始化根實例以前註冊了組件:vue-router
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<
div
id
=
"example"
>
<
my-component
></
my-component
>
</
div
>
// 定義
var MyComponent = Vue.extend({
template: '<
div
>A custom component!</
div
>'
})
// 註冊
Vue.component('my-component', MyComponent)
// 建立根實例
new Vue({
el: '#example'
})
|
渲染爲: json
1
2
3
|
<
div
id
=
"example"
>
<
div
>A custom component!</
div
>
</
div
>
|
注意組件的模板替換了自定義元素,自定義元素的做用只是做爲一個掛載點。能夠用實例選項 replace 決定是否替換。數組
局部註冊
不須要全局註冊每一個組件。可讓組件只能用在其它組件內,用實例選項 components 註冊:
1
2
3
4
5
6
7
8
9
|
var
Child = Vue.extend({
/* ... */
})
var
Parent = Vue.extend({
template:
'...'
,
components: {
// <my-component> 只能用在父組件模板內
'my-component'
: Child
}
})
|
這種封裝也適用於其它資源,如指令、過濾器和過渡。
註冊語法糖
爲了讓事件更簡單,能夠直接傳入選項對象而不是構造器給 Vue.component() 和 component 選項。Vue.js 在背後自動調用 Vue.extend():
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// 在一個步驟中擴展與註冊
Vue.component(
'my-component'
, {
template:
'<div>A custom component!</div>'
})
// 局部註冊也能夠這麼作
var
Parent = Vue.extend({
components: {
'my-component'
: {
template:
'<div>A custom component!</div>'
}
}
})
|
組件選項問題
傳入 Vue 構造器的多數選項也能夠用在 Vue.extend() 中,不過有兩個特例: data 和 el。試想若是咱們簡單地把一個對象做爲 data 選項傳給 Vue.extend():
1
2
3
4
|
var
data = { a: 1 }
var
MyComponent = Vue.extend({
data: data
})
|
這麼作的問題是 `MyComponent` 全部的實例將共享同一個 `data` 對象!這基本不是咱們想要的,所以咱們應當使用一個函數做爲 `data` 選項,讓這個函數返回一個新對象:
1
2
3
4
5
|
var
MyComponent = Vue.extend({
data:
function
() {
return
{ a: 1 }
}
})
|
同理,`el` 選項用在 `Vue.extend()` 中時也須是一個函數。
模板解析
Vue 的模板是 DOM 模板,使用瀏覽器原生的解析器而不是本身實現一個。相比字符串模板,DOM 模板有一些好處,可是也有問題,它必須是有效的 HTML 片斷。一些 HTML 元素對什麼元素能夠放在它裏面有限制。常見的限制:
•a 不能包含其它的交互元素(如按鈕,連接)
•ul 和 ol 只能直接包含 li
•select 只能包含 option 和 optgroup
•table 只能直接包含 thead, tbody, tfoot, tr, caption, col, colgroup
•tr 只能直接包含 th 和 td
在實際中,這些限制會致使意外的結果。儘管在簡單的狀況下它可能能夠工做,可是你不能依賴自定義組件在瀏覽器驗證以前的展開結果。例如 <my-select><option>...</option></my-select> 不是有效的模板,即便 my-select 組件最終展開爲 <select>...</select>。
另外一個結果是,自定義標籤(包括自定義元素和特殊標籤,如 <component>、<template>、 <partial> )不能用在 ul, select, table 等對內部元素有限制的標籤內。放在這些元素內部的自定義標籤將被提到元素的外面,於是渲染不正確。
對於自定義元素,應當使用 is 特性:
1
2
3
|
<
table
>
<
tr
is
=
"my-component"
></
tr
>
</
table
>
|
`` 不能用在 `` 內,這時應使用 ``,`
` 能夠有多個 ``:
1
2
3
4
5
6
|
<
table
>
<
tbody
v-for
=
"item in items"
>
<
tr
>Even row</
tr
>
<
tr
>Odd row</
tr
>
</
tbody
>
</
table
>
|
Props
使用 Props 傳遞數據
組件實例的做用域是孤立的。這意味着不能而且不該該在子組件的模板內直接引用父組件的數據。可使用 props 把數據傳給子組件。
「prop」 是組件數據的一個字段,指望從父組件傳下來。子組件須要顯式地用 props 選項 聲明 props:
1
2
3
4
5
6
7
|
Vue.component(
'child'
, {
// 聲明 props
props: [
'msg'
],
// prop 能夠用在模板內
// 能夠用 `this.msg` 設置
template:
'<span>{{ msg }}</span>'
})
|
而後向它傳入一個普通字符串:
<child msg="hello!"></child>
駝峯式vs.橫槓式
HTML 特性不區分大小寫。名字形式爲 camelCase 的 prop 用做特性時,須要轉爲 kebab-case(短橫線隔開):
1
2
3
4
5
6
7
8
|
Vue.component(
'child'
, {
// camelCase in JavaScript
props: [
'myMessage'
],
template:
'<span>{{ myMessage }}</span>'
})
<!-- kebab-
case
in
HTML -->
<child my-message=
"hello!"
></child>
|
動態 Props
相似於用 v-bind 綁定 HTML 特性到一個表達式,也能夠用 v-bind 綁定動態 Props 到父組件的數據。每當父組件的數據變化時,也會傳導給子組件:
1
2
3
4
5
|
<
div
>
<
input
v-model
=
"parentMsg"
>
<
br
>
<
child
v-bind:my-message
=
"parentMsg"
></
child
>
</
div
>
|
使用 `v-bind` 的縮寫語法一般更簡單:
<child :my-message="parentMsg"></child>
字面量語法 vs. 動態語法
初學者常犯的一個錯誤是使用字面量語法傳遞數值:
<!-- 傳遞了一個字符串 "1" -->
<comp some-prop="1"></comp>
由於它是一個字面 prop,它的值以字符串 `」1」` 而不是以實際的數字傳下去。若是想傳遞一個實際的 JavaScript 數字,須要使用動態語法,從而讓它的值被看成 JavaScript 表達式計算:
<!-- 傳遞實際的數字 -->
<comp :some-prop="1"></comp>
Prop 綁定類型
prop 默認是單向綁定:當父組件的屬性變化時,將傳導給子組件,可是反過來不會。這是爲了防止子組件無心修改了父組件的狀態——這會讓應用的數據流難以理解。不過,也可使用 .sync 或 .once 綁定修飾符顯式地強制雙向或單次綁定:
比較語法:
1
2
3
4
5
6
7
8
|
<!-- 默認爲單向綁定 -->
<
child
:msg
=
"parentMsg"
></
child
>
<!-- 雙向綁定 -->
<
child
:msg.sync
=
"parentMsg"
></
child
>
<!-- 單次綁定 -->
<
child
:msg.once
=
"parentMsg"
></
child
>
|
雙向綁定會把子組件的 msg 屬性同步回父組件的 parentMsg 屬性。單次綁定在創建以後不會同步以後的變化。
注意若是 prop 是一個對象或數組,是按引用傳遞。在子組件內修改它會影響父組件的狀態,不論是使用哪一種綁定類型。
Prop 驗證
組件能夠爲 props 指定驗證要求。當組件給其餘人使用時這頗有用,由於這些驗證要求構成了組件的 API,確保其餘人正確地使用組件。此時 props 的值是一個對象,包含驗證要求:
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
Vue.component(
'example'
, {
props: {
// 基礎類型檢測 (`null` 意思是任何類型均可以)
propA: Number,
// 多種類型 (1.0.21+)
propM: [String, Number],
// 必需且是字符串
propB: {
type: String,
required:
true
},
// 數字,有默認值
propC: {
type: Number,
default
: 100
},
// 對象/數組的默認值應當由一個函數返回
propD: {
type: Object,
default
:
function
() {
return
{ msg:
'hello'
}
}
},
// 指定這個 prop 爲雙向綁定
// 若是綁定類型不對將拋出一條警告
propE: {
twoWay:
true
},
// 自定義驗證函數
propF: {
validator:
function
(value) {
return
value > 10
}
},
// 轉換函數(1.0.12 新增)
// 在設置值以前轉換值
propG: {
coerce:
function
(val) {
return
val +
''
// 將值轉換爲字符串
}
},
propH: {
coerce:
function
(val) {
return
JSON.parse(val)
// 將 JSON 字符串轉換爲對象
}
}
}
})
|
type 能夠是下面原生構造器:
•String
•Number
•Boolean
•Function
•Object
•Array
type 也能夠是一個自定義構造器,使用 instanceof 檢測。
當 prop 驗證失敗了,Vue 將拒絕在子組件上設置此值,若是使用的是開發版本會拋出一條警告。
父子組件通訊
父鏈
子組件能夠用 this.$parent 訪問它的父組件。根實例的後代能夠用 this.$root 訪問它。父組件有一個數組 this.$children,包含它全部的子元素。
儘管能夠訪問父鏈上任意的實例,不過子組件應當避免直接依賴父組件的數據,儘可能顯式地使用 props 傳遞數據。另外,在子組件中修改父組件的狀態是很是糟糕的作法,由於:
1.這讓父組件與子組件緊密地耦合;
2.只看父組件,很難理解父組件的狀態。由於它可能被任意子組件修改!理想狀況下,只有組件本身能修改它的狀態。
自定義事件
Vue 實例實現了一個自定義事件接口,用於在組件樹中通訊。這個事件系統獨立於原生 DOM 事件,用法也不一樣。
每一個 Vue 實例都是一個事件觸發器:
•使用 $on() 監聽事件;
•使用 $emit() 在它上面觸發事件;
•使用 $dispatch() 派發事件,事件沿着父鏈冒泡;
•使用 $broadcast() 廣播事件,事件向下傳導給全部的後代。
不一樣於 DOM 事件,Vue 事件在冒泡過程當中第一次觸發回調以後自動中止冒泡,除非回調明確返回 true。
簡單例子:
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
<!-- 子組件模板 -->
<template id=
"child-template"
>
<input v-model=
"msg"
>
<button v-on:click=
"notify"
>Dispatch Event</button>
</template>
<!-- 父組件模板 -->
<div id=
"events-example"
>
<p>Messages: {{ messages | json }}</p>
<child></child>
</div>
// 註冊子組件
// 將當前消息派發出去
Vue.component(
'child'
, {
template:
'#child-template'
,
data:
function
() {
return
{ msg:
'hello'
}
},
methods: {
notify:
function
() {
if
(
this
.msg.trim()) {
this
.$dispatch(
'child-msg'
,
this
.msg)
this
.msg =
''
}
}
}
})
// 初始化父組件
// 將收到消息時將事件推入一個數組
var
parent =
new
Vue({
el:
'#events-example'
,
data: {
messages: []
},
// 在建立實例時 `events` 選項簡單地調用 `$on`
events: {
'child-msg'
:
function
(msg) {
// 事件回調內的 `this` 自動綁定到註冊它的實例上
this
.messages.push(msg)
}
}
})
|
使用 v-on 綁定自定義事件
上例很是好,不過從父組件的代碼中不能直觀的看到 "child-msg" 事件來自哪裏。若是咱們在模板中子組件用到的地方聲明事件處理器會更好。爲此子組件能夠用 v-on 監聽自定義事件:
<child v-on:child-msg="handleIt"></child>
這樣就很清楚了:當子組件觸發了 `」child-msg」` 事件,父組件的 `handleIt` 方法將被調用。全部影響父組件狀態的代碼放到父組件的 `handleIt` 方法中;子組件只關注觸發事件。
子組件索引
儘管有 props 和 events,可是有時仍然須要在 JavaScript 中直接訪問子組件。爲此可使用 v-ref 爲子組件指定一個索引 ID。例如:
1
2
3
4
5
6
7
|
<
div
id
=
"parent"
>
<
user-profile
v-ref:profile></
user-profile
>
</
div
>
var parent = new Vue({ el: '#parent' })
// 訪問子組件
var child = parent.$refs.profile
|
v-ref 和 v-for 一塊兒用時,ref 是一個數組或對象,包含相應的子組件。
使用 Slot 分發內容
在使用組件時,經常要像這樣組合它們:
1
2
3
4
|
<app>
<app-header></app-header>
<app-footer></app-footer>
</app>
|
注意兩點:
1.<app> 組件不知道它的掛載點會有什麼內容,掛載點的內容是由 <app> 的父組件決定的。
2.<app> 組件極可能有它本身的模板。
爲了讓組件能夠組合,咱們須要一種方式來混合父組件的內容與子組件本身的模板。這個處理稱爲內容分發(或 「transclusion」,若是你熟悉 Angular)。Vue.js 實現了一個內容分發 API,參照了當前 Web 組件規範草稿,使用特殊的 <slot> 元素做爲原始內容的插槽。
編譯做用域
在深刻內容分發 API 以前,咱們先明確內容的編譯做用域。假定模板爲:
<child-component>
{{ msg }}
</child-component>
msg 應該綁定到父組件的數據,仍是綁定到子組件的數據?答案是父組件。組件做用域簡單地說是:
父組件模板的內容在父組件做用域內編譯;子組件模板的內容在子組件做用域內編譯
一個常見錯誤是試圖在父組件模板內將一個指令綁定到子組件的屬性/方法:
<!-- 無效 -->
<child-component v-show="someChildProperty"></child-component>
假定 someChildProperty 是子組件的屬性,上例不會如預期那樣工做。父組件模板不該該知道子組件的狀態。
若是要綁定子組件內的指令到一個組件的根節點,應當在它的模板內這麼作:
1
2
3
4
5
6
7
8
9
|
Vue.component(
'child-component'
, {
// 有效,由於是在正確的做用域內
template:
'<div v-show="someChildProperty">Child</div>'
,
data:
function
() {
return
{
someChildProperty:
true
}
}
})
|
相似地,分發內容是在父組件做用域內編譯。
單個 Slot
父組件的內容將被拋棄,除非子組件模板包含 <slot>。若是子組件模板只有一個沒有特性的 slot,父組件的整個內容將插到 slot 所在的地方並替換它。
<slot> 標籤的內容視爲回退內容。回退內容在子組件的做用域內編譯,當宿主元素爲空而且沒有內容供插入時顯示這個回退內容。
假定 my-component 組件有下面模板:
1
2
3
4
5
6
|
<
div
>
<
h1
>This is my component!</
h1
>
<
slot
>
若是沒有分發內容則顯示我。
</
slot
>
</
div
>
|
父組件模板:
<my-component>
<p>This is some original content</p>
<p>This is some more original content</p>
</my-component>
渲染結果:
1
2
3
4
5
|
<
div
>
<
h1
>This is my component!</
h1
>
<
p
>This is some original content</
p
>
<
p
>This is some more original content</
p
>
</
div
>
|
具名 Slot
<slot> 元素能夠用一個特殊特性 name 配置如何分發內容。多個 slot 能夠有不一樣的名字。具名 slot 將匹配內容片斷中有對應 slot 特性的元素。
仍然能夠有一個匿名 slot,它是默認 slot,做爲找不到匹配的內容片斷的回退插槽。若是沒有默認的 slot,這些找不到匹配的內容片斷將被拋棄。
例如,假定咱們有一個 multi-insertion 組件,它的模板爲:
1
2
3
4
5
|
<
div
>
<
slot
name
=
"one"
></
slot
>
<
slot
></
slot
>
<
slot
name
=
"two"
></
slot
>
</
div
>
|
父組件模板:
1
2
3
4
5
|
<
multi-insertion
>
<
p
slot
=
"one"
>One</
p
>
<
p
slot
=
"two"
>Two</
p
>
<
p
>Default A</
p
>
</
multi-insertion
>
|
渲染結果爲:
1
2
3
4
5
|
<
div
>
<
p
slot
=
"one"
>One</
p
>
<
p
>Default A</
p
>
<
p
slot
=
"two"
>Two</
p
>
</
div
>
|
在組合組件時,內容分發 API 是很是有用的機制。
動態組件
多個組件可使用同一個掛載點,而後動態地在它們之間切換。使用保留的 <component> 元素,動態地綁定到它的 is 特性:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
new Vue({
el: 'body',
data: {
currentView: 'home'
},
components: {
home: { /* ... */ },
posts: { /* ... */ },
archive: { /* ... */ }
}
})
<
component
:is
=
"currentView"
>
<!-- 組件在 vm.currentview 變化時改變 -->
</
component
>
|
keep-alive
若是把切換出去的組件保留在內存中,能夠保留它的狀態或避免從新渲染。爲此能夠添加一個 keep-alive 指令參數:
<component :is="currentView" keep-alive>
<!-- 非活動組件將被緩存 -->
</component>
activate 鉤子
在切換組件時,切入組件在切入前可能須要進行一些異步操做。爲了控制組件切換時長,給切入組件添加 activate 鉤子:
1
2
3
4
5
6
7
8
9
|
Vue.component(
'activate-example'
, {
activate:
function
(done) {
var
self =
this
loadDataAsync(
function
(data) {
self.someData = data
done()
})
}
})
|
注意 `activate` 鉤子只做用於動態組件切換或靜態組件初始化渲染的過程當中,不做用於使用實例方法手工插入的過程當中。
transition-mode
transition-mode 特性用於指定兩個動態組件之間如何過渡。
在默認狀況下,進入與離開平滑地過渡。這個特性能夠指定另外兩種模式:
•in-out:新組件先過渡進入,等它的過渡完成以後當前組件過渡出去。
•out-in:當前組件先過渡出去,等它的過渡完成以後新組件過渡進入。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<!-- 先淡出再淡入 -->
<component
:is=
"view"
transition=
"fade"
transition-mode=
"out-in"
>
</component>
.fade-transition {
transition: opacity .3s ease;
}
.fade-enter, .fade-leave {
opacity: 0;
}
|
雜項
組件和 v-for
自定義組件能夠像普通元素同樣直接使用 v-for:
<my-component v-for="item in items"></my-component>
可是,不能傳遞數據給組件,由於組件的做用域是孤立的。爲了傳遞數據給組件,應當使用 props:
<my-component
v-for="item in items"
:item="item"
:index="$index">
</my-component>
不自動把 item 注入組件的緣由是這會致使組件跟當前 v-for 緊密耦合。顯式聲明數據來自哪裏可讓組件複用在其它地方。
編寫可複用組件
在編寫組件時,記住是否要複用組件有好處。一次性組件跟其它組件緊密耦合不要緊,可是可複用組件應當定義一個清晰的公開接口。
Vue.js 組件 API 來自三部分——prop,事件和 slot:
•prop 容許外部環境傳遞數據給組件;
•事件 容許組件觸發外部環境的 action;
•slot 容許外部環境插入內容到組件的視圖結構內。
使用 v-bind 和 v-on 的簡寫語法,模板的縮進清楚且簡潔:
<my-component
:foo="baz"
:bar="qux"
@event-a="doThis"
@event-b="doThat">
<!-- content -->
<img slot="icon" src="...">
<p slot="main-text">Hello!</p>
</my-component>
異步組件
在大型應用中,咱們可能須要將應用拆分爲小塊,只在須要時才從服務器下載。爲了讓事情更簡單,Vue.js 容許將組件定義爲一個工廠函數,動態地解析組件的定義。Vue.js 只在組件須要渲染時觸發工廠函數,而且把結果緩存起來,用於後面的再次渲染。例如:
1
2
3
4
5
6
7
|
Vue.component(
'async-example'
,
function
(resolve, reject) {
setTimeout(
function
() {
resolve({
template:
'<div>I am async!</div>'
})
}, 1000)
})
|
工廠函數接收一個 resolve 回調,在收到從服務器下載的組件定義時調用。也能夠調用 reject(reason) 指示加載失敗。這裏 setTimeout 只是爲了演示。怎麼獲取組件徹底由你決定。推薦配合使用 Webpack 的代碼分割功能:
1
2
3
4
5
6
|
Vue.component(
'async-webpack-example'
,
function
(resolve) {
// 這個特殊的 require 語法告訴 webpack
// 自動將編譯後的代碼分割成不一樣的塊,
// 這些塊將經過 ajax 請求自動下載。
require([
'./my-async-component'
], resolve)
})
|
資源命名約定
一些資源,如組件和指令,是以 HTML 特性或 HTML 自定義元素的形式出如今模板中。由於 HTML 特性的名字和標籤的名字不區分大小寫,因此資源的名字一般需使用 kebab-case 而不是 camelCase 的形式,這不大方便。
Vue.js 支持資源的名字使用 camelCase 或 PascalCase 的形式,而且在模板中自動將它們轉爲 kebab-case(相似於 prop 的命名約定):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
// 在組件定義中
components: {
// 使用 camelCase 形式註冊
myComponent: {
/*... */
}
}
<!-- 在模板中使用 kebab-
case
形式 -->
<my-component></my-component>
ES6 對象字面量縮寫 也沒問題:
// PascalCase
import TextBox from
'./components/text-box'
;
import DropdownMenu from
'./components/dropdown-menu'
;
export
default
{
components: {
// 在模板中寫做 <text-box> 和 <dropdown-menu>
TextBox,
DropdownMenu
}
}
|
遞歸組件
組件在它的模板內能夠遞歸地調用本身,不過,只有當它有 name 選項時才能夠:
1
2
3
4
5
6
7
8
|
var
StackOverflow = Vue.extend({
name:
'stack-overflow'
,
template:
'<div>'
+
// 遞歸地調用它本身
'<stack-overflow></stack-overflow>'
+
'</div>'
})
|
上面組件會致使一個錯誤 「max stack size exceeded」,因此要確保遞歸調用有終止條件。當使用 Vue.component() 全局註冊一個組件時,組件 ID 自動設置爲組件的 name 選項。
片段實例
在使用 template 選項時,模板的內容將替換實例的掛載元素。於是推薦模板的頂級元素始終是單個元素。
不這麼寫模板:
<div>root node 1</div>
<div>root node 2</div>
推薦這麼寫:
<div>
I have a single root node!
<div>node 1</div>
<div>node 2</div>
</div>
下面幾種狀況會讓實例變成一個片段實例:
1.模板包含多個頂級元素。
2.模板只包含普通文本。
3.模板只包含其它組件(其它組件多是一個片斷實例)。
4.模板只包含一個元素指令,如 <partial> 或 vue-router 的 <router-view>。
5.模板根節點有一個流程控制指令,如 v-if 或 v-for。
這些狀況讓實例有未知數量的頂級元素,它將把它的 DOM 內容看成片段。片段實例仍然會正確地渲染內容。不過,它沒有一個根節點,它的 $el 指向一個錨節點,即一個空的文本節點(在開發模式下是一個註釋節點)。
可是更重要的是,組件元素上的非流程控制指令,非 prop 特性和過渡將被忽略,由於沒有根元素供綁定:
<!-- 不能夠,由於沒有根元素 -->
<example v-show="ok" transition="fade"></example>
<!-- props 能夠 -->
<example :prop="someData"></example>
<!-- 流程控制能夠,可是不能有過渡 -->
<example v-if="ok"></example>
固然片段實例有它的用處,不過一般給組件一個根節點比較好。它會保證組件元素上的指令和特性能正確地轉換,同時性能也稍微好些。
內聯模板
若是子組件有 inline-template 特性,組件將把它的內容看成它的模板,而不是把它看成分發內容。這讓模板更靈活。
<my-component inline-template>
<p>These are compiled as the component's own template</p>
<p>Not parent's transclusion content.</p>
</my-component>
可是 inline-template 讓模板的做用域難以理解,而且不能緩存模板編譯結果。最佳實踐是使用 template 選項在組件內定義模板。