什么是組件?
在說之前我們先搞清楚什么是組件?這樣對我們下邊的學習是很有幫助的。
組件(Component)是Vue.js最強大的功能之一。組件可以擴展HTML元素,封裝可以重復使用的代碼。在較高層次上,組件就是自定義元素,Vue.js的編輯器為它添加特殊功能。在有些情況下,組件也可以是原生元素的形式,以is
特性進行擴展。
怎么使用組件?
說道這里,組件是什么,我們都有了清楚的了解,但是怎么使用呢?
首先,我們要進行注冊,才能進行使用
注冊
之前我們也說過,可以通過new
來創建一個VUE實例
new Vue ({ 'el' : '#element', //選項 })
- 1
- 2
- 3
- 4
這樣,一個vue實例我們就創建成功了,這時候就要注冊一個組件,我們可以通過Vue.component(tagName,options)
。由於作用域的不同,組件也是分為全局組件和局部組件的,我們先來說全局組件。
Vue.component('my-component',{ //選項 })
- 1
- 2
- 3
一個全局組件就這樣組冊成功了,此后便可以在父實例的模塊中以自定義元素<my-component></my-component>
的形式進行使用。一定切記,要確保在初始化根實例之前注冊了組件:
<div id='app'> <my-component></my-component> </div>
- 1
- 2
- 3
//注冊組件 Vue.component('my-component',{ 'template' : '<div>一個全局組件</div>' }) //創建根實例 new Vue({ 'el' : '#app', })
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
以上渲染出來就是:
<div id='app'> <div>一個全局組件</div> </div>
- 1
- 2
- 3
局部注冊
在開發中,我們不必在全局注冊每個組件。通過使用組件實例選項注冊,可以使組件僅在另一個實例/組件的作用域可用,代碼如下:
var Child = {
'template' : '<div>一個組件</div>' } new Vue({ 'el' : '#app', //... 'component' : { 'my-component' : Child //此時該模板只能在父實例中使用 } })
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
這種封裝方式也可適用於其他可注冊的Vue功能。如指令
DOM模板解析說明
當使用DOM作為模板時(例如,將el
選項掛載到一個已知的元素上),你會受到HTML的一些限制,因為Vue只有在瀏覽器解析和標准化HTML后才能獲取模板內容。尤其像這些元素<ul>,<ol>,<table>,<select>
限制了能被它保過的元素,而一些像option
這樣的元素只能出現在某些其他元素的內部。
在自定義組件中使用這些受限制的元素時會導致一些問題,例如:
<table>
<my-row>...</my-row> </table>
- 1
- 2
- 3
自定義組件<my-row>
被認為是無效的內容,因此在渲染的時候會出現導致錯誤。變通的方案是使用特殊的is
屬性:
<table>
<tr is='my-row'>...</tr> </table>
- 1
- 2
- 3
應當注意,如果我們使用下面來源之一的字符串模板,這些限制將不適用:
<script type='text/x-template'>
- JavaScript內聯模板字符串
.Vue
組件
因此,有必要的話請使用字符串模板
data
必須是函數
通過Vue構造器傳入的各種選項大多數都可以在組件里使用。data
是個例外,它必須是函數。實際上,如果我們這樣做:
Vue.component('my-component',{ 'template' : '<span>{{message}}</span>', 'data' : { 'message' : 'hello' } })
- 1
- 2
- 3
- 4
- 5
- 6
那么Vue會停止,並在控制台發出警告,告訴你在組件中data
必須是函數。理解這種規則存在的意義很有幫助,讓我們假設用如下方式來避開Vue的警告:
<div id='app'> <simple-counter></simple-counter> <simple-counter></simple-counter> <simple-counter></simple-counter> </div>
- 1
- 2
- 3
- 4
- 5
var data = {counter : 0} Vue.component('simple-counter',{ 'template' : '<button v-on:click='counter += 1'>{{counter}}</button>' //技術上data是一個函數,所以Vue不會警告 //但是我們返回給每個組件的實例調用了同一個data對象 'data' : function (){ return data } }) new Vue({ 'el' : '#app' })
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
由於這三個組件共享一個data
,因此增加一個counter會影響所有組件!很明顯,這樣做是不對的。我們可以通過為每個組件返回全新的data對象來解決這個問題,如下:
data : function (){ return { counter : 0 } }
- 1
- 2
- 3
- 4
- 5
現在每個counter都有它自己內部的狀態了。
構成組件
組件意味着協同工作,通常父子組件會是這樣的關系:組件A在它的模板中使用了組件B。它們之間必然需要相互通信:父組件要給子組件傳遞數據,子組件需要將它內部發生的事情告知給父組件。然而,在一個良好定義的接口中盡可能將父子組件解耦是很重要的。這保證了每個組件可以在相對隔離的環境中書寫和理解,也大幅度提高了組件的可維護性和可重用性。
在Vue中,父子組件的關系可以總結為 props down, events up。父組件通過 props 向下傳遞數據給子組件,子組件通過 events 給父組件發送消息。看看它們是怎么工作的。如圖: