閱讀目錄
- 1.vue組件注冊步驟
- 2.理解組件的創建和注冊。
- 3.理解Vue全局注冊和局部注冊
- 4.理解父組件和子組件
- 5.理解組件的語法糖。
- 6.學會使用 script或 template 標簽
- 7.理解使用props
1.vue組件注冊步驟
Vue.js 的組件有三個步驟: 創建組件構造器(Vue.extend()方法 ),注冊組件(Vue.component())和實例化組件。
如下demo:
<!DOCTYPE html> <html> <body> <head> <title>演示Vue</title> </head> <div id="container"> <component1></component1> </div> </body> <script src="./vue.js"></script> <script type="text/javascript"> // 1. 創建一個組件構造器 var component1 = Vue.extend({ template: '<div>hello world</div>' }); // 2. 注冊組件,並指定組件的標簽為<component1> Vue.component('component1', component1); // 3. 實例化組件 new Vue({ el: '#container' }); </script> </html>
瀏覽器編譯后html結構會變為
<div id="container"> <div>hello world</div> </div>
頁面運行顯示為
hello world
2.理解組件的創建和注冊。
2-1 Vue.extend() 是Vue構造器的擴展,調用Vue.extend()創建的是一個組件構造器,該構造器有一個選項對象,選項對象的template屬性用於定義組件要渲染的html。
2-2 Vue.component() 是注冊組件,需要2個參數,第一個參數是自定義組件的標簽,第二個參數是組件的構造器。
2-3 組件需要掛載到某個Vue的實例下,否則不生效。
如下實例:
<!DOCTYPE html> <html> <body> <head> <title>演示Vue</title> </head> <div id="container1"> <component1></component1> </div> <div id="container2"> <component1></component1> </div> <div id="container3"> <component1></component1> </div> </body> <script src="./vue.js"></script> <script type="text/javascript"> // 1. 創建一個組件構造器 var component1 = Vue.extend({ template: '<div>hello world</div>' }); // 2. 注冊組件,並指定組件的標簽為<component1> Vue.component('component1', component1); // 3. 實例化組件 container1 new Vue({ el: '#container1' }); // 3. 實例化組件 container2 new Vue({ el: '#container2' }); // 不實例化 container3 因此第三個自定義標簽是不會生效的 </script> </html>
最終代碼被渲染成為如下:
<div id="container1"><div>hello world</div></div> <div id="container2"><div>hello world</div></div>
3.理解Vue全局注冊和局部注冊
調用Vue.component()注冊組件時,組件的注冊是全局的,如果想要使用組件的局部注冊的話,可以用選項對象的components屬性實現局部注冊。
如下代碼:中間就把第二步注冊組件哪項移到實例化組件里面來了;如下代碼:
<!DOCTYPE html> <html> <body> <head> <title>演示Vue</title> </head> <div id="container1"> <component1></component1> </div> <!-- 不能使用component1組件,因為它是container1里面局部注冊的 --> <div id="container2"> <component1></component1> </div> </body> <script src="./vue.js"></script> <script type="text/javascript"> // 1. 創建一個組件構造器 var component1 = Vue.extend({ template: '<div>hello world</div>' }); // 3. 實例化組件 container1 new Vue({ el: '#container1', components: { 'component1': component1 } }); // 實例化container2 是不生效的 new Vue({ el: '#container2' }) </script> </html>
實例化container2 是不生效的,並且在瀏覽器控制台會報如下錯誤:

4.理解父組件和子組件。
在一個組件中包含另一個組件,那么另一個組件就是該組件的子組件。
如下代碼:
<!DOCTYPE html> <html> <body> <head> <title>演示Vue</title> </head> <div id="container1"> <parent-component></parent-component> </div> </body> <script src="./vue.js"></script> <script type="text/javascript"> // 1. 創建一個組件構造器 var Child = Vue.extend({ template: '<div>hello world</div>' }); var Parent = Vue.extend({ // 在組件內部使用<child-component>組件 template: '<div>hello world <child-component></child-component></div>', components: { // 局部注冊Child組件 'child-component': Child } }); // 全局注冊Parent組件 Vue.component('parent-component', Parent); // 實例化組件 new Vue({ el: '#container1' }) </script> </html>
簡單理解代碼如下:
1. var Child = Vue.extend(...) 定義一個Child組件構造器。
2. var Parent = Vue.extend(...) 定義一個Parent組件構造器。
3. components: {'child-component': Child}, 將Child組件注冊到Parent組件,並將Child組件的標簽設置為 child-component;
4. template: 渲染html模板,找到template選項,然后使用 child-component組件。
5. 注冊Parent組件 Vue.component('parent-component', Parent);
6. 最后實例化組件,需要到html元素為id='container1'里面去。
Child組件是在Parent組件中注冊的,只能在Parent組件中注冊的。如下幾種情況都不行的。
4-1 以子標簽的形式在父組件中使用;如下代碼:
<!DOCTYPE html> <html> <body> <head> <title>演示Vue</title> </head> <div id="container1"> <parent-component> <child-component></child-component> </parent-component> </div> </body> <script src="./vue.js"></script> <script type="text/javascript"> // 1. 創建一個組件構造器 var Child = Vue.extend({ template: '<div>hello world</div>' }); var Parent = Vue.extend({ // 在組件內部使用<child-component>組件 template: '<div>hello world</div>', components: { // 局部注冊Child組件 'child-component': Child } }); // 全局注冊Parent組件 Vue.component('parent-component', Parent); // 實例化組件 new Vue({ el: '#container1' }) </script> </html>
上面調用子組件的方式是無效的,因為在js里面當父組件要需要的html模板template的內容的時候已經決定了需要渲染什么,所以當parent-component運行的時候,在父組件使用自定義的子標簽。
運行時會當做html的普通標簽來渲染,但是它又不是普通的html標簽,因此會被忽略掉。
4-2. 在父組件標簽外使用子組件。
<div id="container1"> <parent-component></parent-component> <child-component></child-component> </div>
js代碼還是上面的一樣,運行完成后,在瀏覽器下會報錯如下:
5.理解組件的語法糖。
我們可以使用更簡單的方式來注冊組件。
5-1 使用Vue.component()直接創建和注冊組件。如下代碼:
<!DOCTYPE html> <html> <body> <head> <title>演示Vue</title> </head> <div id="container1"> <component1></component1> </div> </body> <script src="./vue.js"></script> <script type="text/javascript"> // 全局注冊 Vue.component('component1', { template: '<div>hello world222</div>' }); // 實例化 var vm1 = new Vue({ el: '#container1' }); </script> </html>
Vue.component()的第一個參數是標簽名稱,第二個參數是一個選項對象,使用選項對象的template屬性定義,使用該方式,在Vue源碼中會調用Vue.extend()方法。
注意: 在template元素中需要使用一個標簽容器包圍,比如我們可以把div元素去掉的話,只放內容的話,會報錯如下:
5-2 在選項對象的components屬性中實現局部注冊。
<!DOCTYPE html> <html> <body> <head> <title>演示Vue</title> </head> <div id="container1"> <component1></component1> </div> <div id="container2"> <component2></component2> <component3></component3> </div> </body> <script src="./vue.js"></script> <script type="text/javascript"> // 全局注冊,my-component1是標簽名稱 Vue.component('component1',{ template: '<div>This is the first component!</div>' }) var vm1 = new Vue({ el: '#container1' }) // 實例化 局部注冊 var vm1 = new Vue({ el: '#container2', components: { // 局部注冊, component2 是標簽名稱 'component2': { template: '<div>component2</div>' }, // 局部注冊,component3 是標簽名稱 'component3': { template: '<div>component3</div>' } } }); </script> </html>
6.學會使用 script或 template 標簽。
雖然語法糖簡化了組件注冊,但是在template選項中拼接了html元素,這導致View和C層的高耦合性。幸運的是Vue.js 提供了2種方式將javascript中的html模板分離出來。
6-1 使用script標簽, 如下代碼:
<!DOCTYPE html> <html> <body> <head> <title>演示Vue</title> </head> <div id="container1"> <component1></component1> </div> <script type='text/x-template' id="myComponent"> <div>hello world!!!!!</div> </script> </body> <script src="./vue.js"></script> <script type="text/javascript"> new Vue({ el: '#container1', components: { 'component1': { template: '#myComponent' } } }) </script> </html>
注意: 使用<script>標簽時,type指定為 text/x-template,是告訴瀏覽器這不是一段js腳本,瀏覽器在解析html文檔時會忽略script標簽內定義的內容。
6-2 使用<template>標簽。不需要指定type屬性。
如下代碼:
<!DOCTYPE html> <html> <body> <head> <title>演示Vue</title> </head> <div id="container1"> <component1></component1> </div> <template id="myComponent"> <div>hello world2222!!!!!</div> </template> </body> <script src="./vue.js"></script> <script type="text/javascript"> new Vue({ el: '#container1', components: { 'component1': { template: '#myComponent' } } }) </script> </html>
7.理解使用props。
父組件的數據如何傳給子組件呢?可以使用props把數據傳給子組件。
代碼如下:
<!DOCTYPE html> <html> <body> <head> <title>演示Vue</title> </head> <div id="container1"> <component1 v-bind:my-name="name" v-bind:my-age="age"></component1> </div> <template id="myComponent"> <table> <tr> <th colspan="2"> 子組件數據 </th> </tr> <tr> <td>myName</td> <td>{{ myName }}</td> </tr> <tr> <td>myAge</td> <td>{{ myAge }}</td> </tr> </table> </template> </body> <script src="./vue.js"></script> <script type="text/javascript"> new Vue({ el: '#container1', data: { name: 'longen', age: 30 }, components: { 'component1': { template: '#myComponent', props: ['myName', 'myAge'] } } }) </script> </html>
注意: 在子組件中定義prop時,使用了camelCase命名法。由於HTML特性不區分大小寫,camelCase的prop用於特性時,會轉為短橫線隔開的,比如上面的代碼:
在props中定義的myName,在用作特性時需要轉換為 my-name
理解prop的單向綁定
既然父組件使用props把數據傳給了子組件,那么如果子組件修改了數據,對父組件是否有影響呢?
看下面的代碼如下:
<!DOCTYPE html> <html> <body> <head> <title>演示Vue</title> <style> * { margin: 0; padding: 0; box-sizing: border-box } html { font-size: 12px; font-family: Ubuntu, simHei, sans-serif; font-weight: 400 } body { font-size: 1rem } table, td, th { border-collapse: collapse; border-spacing: 0 } table { width: 100%; margin: 20px; } td, th { border: 1px solid #bcbcbc; padding: 5px 10px } th { background: #42b983; font-size: 1.2rem; font-weight: 400; color: #fff; cursor: pointer } tr:nth-of-type(odd) { background: #fff } tr:nth-of-type(even) { background: #eee } fieldset { border: 1px solid #BCBCBC; padding: 15px; } input { outline: none } input[type=text] { border: 1px solid #ccc; padding: .5rem .3rem; } input[type=text]:focus { border-color: #42b983; } button { outline: none; padding: 5px 8px; color: #fff; border: 1px solid #BCBCBC; border-radius: 3px; background-color: #009A61; cursor: pointer; } button:hover{ opacity: 0.8; } #container1 { margin: 0 auto; max-width: 480px; } </style> </head> <div id="container1"> <table> <tr> <th colspan="3"> 父組件數據 </th> </tr> <tr> <td>name</td> <td>{{ name }}</td> <td><input type='text' v-model = "name" /></td> </tr> <tr> <td>age</td> <td>{{ age }}</td> <td><input type="text" v-model="age" /></td> </tr> </table> <component1 v-bind:my-name="name" v-bind:my-age="age"></component1> </div> <template id="myComponent"> <table> <tr> <th colspan="3"> 子組件數據 </th> </tr> <tr> <td>myName</td> <td>{{ myName }}</td> <td><input type="text" v-model="myName" /></td> </tr> <tr> <td>myAge</td> <td>{{ myAge }}</td> <td><input type="text" v-model="myAge" /></td> </tr> </table> </template> </body> <script src="./vue.js"></script> <script type="text/javascript"> new Vue({ el: '#container1', data: { name: 'longen', age: 30 }, components: { 'component1': { template: '#myComponent', props: ['myName', 'myAge'] } } }) </script> </html>