組件 (Component) 是 Vue.js 最強大的功能之一。組件能夠擴展 HTML 元素,封裝可重用的代碼。在較高層面上,組件是自定義元素,Vue.js 的編譯器爲它添加特殊功能。在有些狀況下,組件也能夠表現爲用is 特性進行了擴展的原生 HTML 元素。全部的 Vue 組件同時也都是 Vue 的實例,因此可接受相同的選項對象 (除了一些根級特有的選項) 並提供相同的生命週期鉤子。css
註冊全局組件:可使用可使用 Vue.component(tagName, options)html
1 Vue.component('my-component', { 2 // 選項 3 })
組件在註冊以後,即可以做爲自定義元素 在一個實例的模板中使用。注意確保在初始化根實例以前註冊組件:vue
1 <div id="example"> 2 <my-component></my-component> 3 </div>
測試實例:瀏覽器
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Vue 測試實例 - 全局組件</title> 6 <script src="https://cdn.bootcss.com/vue/2.2.2/vue.min.js"></script> 7 </head> 8 <body> 9 <div id="app"> 10 <!-----引用組件-----> 11 <my-component></my-component> 12 </div> 13 14 <script> 15 // 註冊 16 Vue.component('my-component', { 17 template: '<h3>我是全局組件!</h3>' 18 }) 19 // 建立根實例 20 new Vue({ 21 el: '#app' 22 }) 23 </script> 24 </body> 25 </html>
你沒必要把每一個組件都註冊到全局。你能夠經過某個 Vue 實例/組件的實例選項 components註冊僅在其做用域中可用的組件: app
1 var Child = { 2 template: '<h3>我是局部組件!</h3>' 3 }new Vue({ // ... components: { // <my-component> 將只在父組件模板中可用 'my-component': Child }})
例子2:函數
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Vue 測試實例 - 局部組件</title> 6 <script src="https://cdn.bootcss.com/vue/2.2.2/vue.min.js"></script> 7 </head> 8 <body> 9 <div id="app"> 10 <!-----引用組件-----> 11 <my-component></my-component> 12 </div> 13 14 <script> 15 var Child = { 16 template: '<h3>自定義組件!</h3>' 17 } 18 19 // 建立根實例 20 new Vue({ 21 el: '#app', 22 components: { 23 // <my-component> 將只在父組件模板可用 24 'my-component': Child 25 } 26 }) 27 </script> 28 </body> 29 </html>
當使用 DOM 做爲模板時 (例如,使用 el 選項來把 Vue 實例掛載到一個已有內容的元素上),你會受到 HTML 自己的一些限制,由於 Vue 只有在瀏覽器解析、規範化模板以後才能獲取其內容。尤爲要注意,像ul、ol、select、table這樣的元素裏包含的元素有限制,而另外一些像option的元素只能出如今某些特定元素的內部,在自定義組建中使用這些受限制的元素,容易致使一些問題。測試
1 <table> 2 <my-row>...</my-row> 3 </table>
應當注意,若是使用來自如下來源之一的字符串模板,則沒有這些限制:spa
<script type="text/x-template">
JavaScript 內聯模板字符串
.vue 組件
所以,請儘量使用字符串模板。code
上面的意思是下面的例子是會不行的:component
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Vue 測試實例</title> 6 <script src="https://cdn.bootcss.com/vue/2.2.2/vue.min.js"></script> 7 </head> 8 <body> 9 <div id="app"> 10 <select> 11 <optioncomp></optioncomp> 12 </select> 13 </div> 14 15 <script> 16 new Vue({ 17 el: '#app', 18 components:{ 19 'optioncomp':{ 20 template: '<option >a</option>' 21 } 22 } 23 }) 24 </script> 25 </body> 26 </html>
可是用is特殊屬性能夠:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Vue 測試實例</title> 6 <script src="https://cdn.bootcss.com/vue/2.2.2/vue.min.js"></script> 7 </head> 8 <body> 9 <div id="app"> 10 <select> 11 <option is="optioncomp"></option> 12 </select> 13 </div> 14 15 <script> 16 new Vue({ 17 el: '#app', 18 components:{ 19 'optioncomp':{ 20 template: '<option >a</option>' 21 } 22 } 23 }) 24 </script> 25 </body> 26 </html>
或者temp模板標籤也能夠:
1 <body> 2 <div id="app"> 3 <select> 4 <option is="optioncomp"></option> 5 </select> 6 7 <!--模板內容存放區域--> 8 <script type="x-template" id="optioncompTemp"> 9 <option >a</option> 10 </script> 11 </div> 12 13 <script src="https://cdn.bootcss.com/vue/2.2.2/vue.min.js"></script> 14 <script> new Vue({ el: '#app', components:{ 'optioncomp':{ template: '#optioncompTemp' } } }) </script></body>
或者內聯模板字符串也行
1 <body> 2 <div id="app"> 3 <selectcomp></selectcomp> 4 </div> 5 6 <script src="https://cdn.bootcss.com/vue/2.2.2/vue.min.js"></script> 7 <script> Vue.component('optioncomp',{ template: '<option >a</option>' }); new Vue({ el: '#app', components:{ 'selectcomp':{ template: ' <select> 8 <optioncomp></optioncomp></select>' } } }) </script></body>
data必須是函數 構造 Vue 實例時傳入的各類選項大多數均可以在組件裏使用。只有一個例外:data 必須是函數。實際上,若是你這麼作:
1 <code class="language-html">Vue.component('my-component', { 2 template: '<span>{{ message }}</span>', 3 data: { 4 message: 'hello' 5 } 6 })</code>
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Vue 測試實例</title> 6 <script src="https://cdn.bootcss.com/vue/2.2.2/vue.min.js"></script> 7 </head> 8 <body> 9 <div id="example-2"> 10 <simple-counter></simple-counter> 11 <simple-counter></simple-counter> 12 <simple-counter></simple-counter> 13 </div> 14 15 <script> 16 var data = {counter:0}; 17 Vue.component('simple-counter',{ 18 template:'<button v-on:click="counter+=1">{{counter}}</button>', 19 data:function(){ 20 return data; 21 } 22 }) 23 new Vue({ 24 el: '#example-2' 25 }) 26 </script> 27 </body> 28 </html>
因爲這三個組件實例共享了同一個 data 對象,所以遞增一個 counter 會影響全部組件!這就錯了。咱們能夠經過爲每一個組件返回全新的數據對象來修復這個問題:
1 data: function () { 2 return { 3 counter: 0 4 } 5 }
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Vue 測試實例</title> 6 <script src="https://cdn.bootcss.com/vue/2.2.2/vue.min.js"></script> 7 </head> 8 <body> 9 <div id="example-2"> 10 <simple-counter></simple-counter> 11 <simple-counter></simple-counter> 12 <simple-counter></simple-counter> 13 </div> 14 15 <script> 16 17 Vue.component('simple-counter',{ 18 template:'<button v-on:click="counter+=1">{{counter}}</button>', 19 data: function () { 20 return { 21 counter: 0 22 } 23 } 24 }) 25 new Vue({ 26 el: '#example-2' 27 }) 28 </script> 29 </body> 30 </html>