一、什么組件
組件 (Component) 是 Vue.js 的重要組成部分。能夠讓你在復(fù)雜的應(yīng)用中拆分成獨立模塊。使用組件可以擴展 HTML 元素,封裝可重用的代碼,組件是自定義元素,Vue.js 的編譯器為它添加特殊功能。在有些情況下,組件也可以表現(xiàn)為用
is特性進行了擴展的原生 HTML 元素。Vue提供一個組件系統(tǒng),提供了一種抽象,讓我們可以使用獨立可復(fù)用的小組件來構(gòu)建大型應(yīng)用,任意類型的應(yīng)用界面都可以抽象為一個組件樹
開發(fā)組件時應(yīng)當(dāng)遵循這三點:
- 高內(nèi)聚
- 低耦合
- 高可用
所謂高內(nèi)聚,低耦合要求組件內(nèi)部應(yīng)當(dāng)包含所有組件需要的資源,盡量不與其他模塊互相依賴,開發(fā)者能簡單的即插即用。
而高可用則有多種含義:得跑的起來,經(jīng)得起測試,易于擴展
二、基本使用
1、概要
Vue的組件使用基本分為三個步驟:
- 創(chuàng)建組件構(gòu)造器
- 注冊組件
- 使用組件
image
2、基礎(chǔ)使用
-
html
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="html" cid="n31" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit;"><div id="app">
<my-component></my-component>
<my-component></my-component>
</div></pre> -
js
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="html" cid="n34" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit;"><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 全局注冊組件
Vue.component("my-component", {
template: "<div id='header'>我是組件</div>"
});let app = new Vue({
// 掛載
el: '#app',
})
</script></pre> -
注意
對于組件命名,盡量使用小寫,并且包含一個短杠例如my-component,也可以使用MyComponent
一定要在掛載的元素區(qū)域使用
組件是可以復(fù)用的
三、注冊方式
1、說明
組件常見的注冊方式有兩種,實際上有7種左右:
- 全局注冊
- 局部注冊
2、全局注冊
-
說明
使用
Vue.component()可以注冊一個全局組件,這樣該組件可以在任意Vue實例下使用,或者另外一種注冊方式,通過 全局API:
Vue.extend() -
語法格式
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="vue" cid="n61" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit;">Vue.component(id, [definition] )</pre>
-
參數(shù)說明
參數(shù) 參數(shù)類型 說明 id 字符串類型 設(shè)置組件的名字 definition 方法或者Object 組件 -
示例代碼
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="html" cid="n79" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit;"><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<app-component></app-component>
</div>
<div id="app1">
<app-component></app-component>
</div>
?
<script>
/*- 注意 組件最外層只能有一個元素
Vue.component('app-component', {
template: "<div id='header'>我是組件</div><div>這樣寫是錯誤的</div>"
});
*/
Vue.component("app-component", {
template: '<p>全局注冊組件</p>',
});
new Vue({
el: "#app",
});new Vue({
el: "#app1"
});</script>
?
?
<div id="app">
<div>小明<button>修改姓名</button></div>
</div>
?
<div id="app1">
<div>小明<button>修改姓名</button></div>
</div></pre> - 注意 組件最外層只能有一個元素
-
總結(jié)
組件必須有一個templtae選項
全局組件必須寫在new Vue()創(chuàng)建之前,才在該根元素下面生效
模板里面第一級只能有一個標(biāo)簽,不能并行
3、局部注冊
-
說明
如果不需要全局注冊,或者是讓組件使用在其它組件內(nèi),可以用選項對象的components屬性實現(xiàn)局部注冊。
-
示例代碼
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="html" cid="n96" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit;">?
<div id="app">
<local></local>
</div>
?
<script>
let localComponent = {
template: '<p>這個是局部注冊組件</p>'
};new Vue({
el: '#app',
components: {
// local 這個名字是用在html中的,說白了 就是自定義了一個html 標(biāo)簽而已
'local': localComponent,
// 也可以使用 簡寫方式
// localComponent,
}
})
</script>
?
<div id="app">
<p>這個是局部注冊組件</p>
</div></pre>
4、使用script或template標(biāo)簽
-
說明
在template選項中拼接HTML元素比較麻煩,這也導(dǎo)致了HTML和JavaScript的高耦合性。 慶幸的是,Vue.js提供了兩種方式將定義在JavaScript中的HTML模板分離出來。
-
使用
script(了解)<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="html" cid="n105" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit;"><div id="app">
<my-component></my-component>
</div>
?
<script type="text/x-template" id="myComponent">
<div>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
</script>
?
<script>
let myComponent = {
// template選項現(xiàn)在不再是HTML元素,而是一個id(myComponent),Vue.js根據(jù)這個id查找對應(yīng)的元素,然后將這個元素內(nèi)的HTML作為模板進行編譯。
template: '#myComponent'
};
new Vue({
el: '#app',
components: {
'my-component': myComponent
}
})
</script></pre> -
使用
template<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="html" cid="n108" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit;">
?
<div id="app">
<my-component></my-component>
</div>
?
<template id="myComponent">
<div>使用template標(biāo)簽</div>
</template>
?
<script>
Vue.component('my-component', {
template: '#myComponent'
});new Vue({
el: '#app'
})
</script></pre> -
總結(jié)
在理解了組件的創(chuàng)建和注冊過程后,我建議使用
<template>標(biāo)簽來定義組件的HTML模板。這楊可以使HTML代碼和JavaScript代碼是分離的,便于閱讀和維護。
在Vue.js中,也可創(chuàng)建.vue后綴的文件,在.vue文件中定義組件,這個內(nèi)容我會在后面的腳手架搭建的時候會介紹。
5、組件的el和data選項
-
說明
傳入Vue構(gòu)造器選項el、data、computed、watch、methods 以及生命周期鉤子等也可以用在 Vue.extend() 或Vue.component()中,不過有兩個特例: data 和el。
Vue.js規(guī)定:在定義組件的選項時,data和el選項必須使用函數(shù)。
-
舉個栗子
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="html" cid="n125" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit;"><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<app-component></app-component>
</div>
<div id="app1">
<app-component></app-component>
</div>
<script>
Vue.component("app-component", {
template: '<div> ' +
'{{name}}' +
'<button @click="changName">修改姓名</button>' +
'</div>',
// 注意data必須是函數(shù)
data: function () {
return {
name: "小明",
}
},
methods: {
changName: function () {
this.name = "小紅"
}
}
});
// 實例1
new Vue({
el: "#app",
});
// 實例2
new Vue({
el: "#app1"
});</script>
<div id="app">
<div>小明<button>修改姓名</button></div>
</div>
?
<div id="app1">
<div>小明<button>修改姓名</button></div>
</div>
?</pre>
四、is 特性擴展
-
說明
什么是is特性,首先得先說Vue的解析器使用的瀏覽器的的原生模板,原生模板對一些HTML元素了做了一些限制,例如:
ulol只能包含li元素table只能包含thead, tr ,tbody等a不能包含其他交互元素如button等
當(dāng)有些元素內(nèi)部不能使用自定義標(biāo)簽或者自定義標(biāo)簽內(nèi)也不能放某些特殊的標(biāo)簽,這時候就要用is代替一下,讓html語法符合規(guī)則驗證。is屬于指定要在內(nèi)部使用的標(biāo)簽。 在自定義組件中使用這些受限制的元素時會導(dǎo)致一些問題
-
示例代碼
<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="html" cid="n142" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit;"><div id="app">
<table>
<tbody is="t-component"></tbody>
</table>
<ul>
<li is="p-component"></li>
<li is="p-component"></li>
<li is="p-component"></li>
<li is="p-component"></li>
<li is="p-component"></li>
<li is="p-component"></li>
</ul></div>
<script src="js/vue.js"></script>
<script>
/table子組件/
let trComponent = {
template: "<h>is特性演示-table</h>"
};
/* ul子組件 */
let pComponent = {
template: "<p>is特性演示-ul子組件演示</p>"
};new Vue({ el: '#app', // 注冊組件 components: { 't-component': trComponent, 'p-component': pComponent } })</script></pre>
五、組件嵌套
-
說明
在組件中使用components定義子組件,可以定義多個,定義好以后,就可以在組件的模板中使用子組件了
-
示例代碼
<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="html" cid="n151" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit;"><div id="app">
<app-container/>
</div>
<template id="appContainer">
<div>
<app-header></app-header>
<app-content></app-content>
<app-footer></app-footer>
</div>
</template>
<template id="header">
<div>這是頭部</div>
</template>
<template id="content">
<div>這個是內(nèi)容部分</div>
</template>
<template id="footer">
<div>這個是底部</div>
</template>
<script>new Vue({ el: '#app', components: { 'app-container': { /*全局注冊父組件*/ template: '#appContainer', /* 注冊子組件 */ components: { 'app-footer': { template: '#footer' }, 'app-content': { template: '#content' }, 'app-header': { template: '#header' } } } } });</script></pre>
