閱讀目錄
- 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>