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