第三天:Vue的组件化
1、認(rèn)識(shí)組件化
我們將一個(gè)完整的頁(yè)面分成很多個(gè)組件,每個(gè)組件都用于實(shí)現(xiàn)頁(yè)面的一個(gè)功能塊,而每一個(gè)組件又可以進(jìn)行細(xì)分。
組件化是Vuejs中的重要思想,它提供了一種抽象,讓我們可以開(kāi)發(fā)出一個(gè)個(gè)獨(dú)立可復(fù)用的小組件來(lái)構(gòu)造我們的應(yīng)用,任何的應(yīng)用都會(huì)被抽象成一顆組件樹(shù)。
組件化思想的應(yīng)用使我們?cè)陂_(kāi)發(fā)中盡可能的將頁(yè)面拆分成一個(gè)個(gè)小的、可復(fù)用的組件,讓我們的代碼更加方便組織和管理,并且擴(kuò)展性也更強(qiáng)。
2、注冊(cè)組件的基本步驟
組件的使用分成三個(gè)步驟:
1、創(chuàng)建組件構(gòu)造器
2、注冊(cè)組件
3、使用組件
基本使用:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<div id="app"><!--3、使用組件--><my-cpn></my-cpn><my-cpn></my-cpn>
</div><script src="../js/vue.js"></script>
<script>//1、創(chuàng)建組件構(gòu)造器對(duì)象const cpnC = Vue.extend({template: `<div><h2>我是標(biāo)題</h2><p>我是內(nèi)容1</p><p>我是內(nèi)容2</p></div>`})//2、注冊(cè)組件Vue.component('my-cpn',cpnC)const app = new Vue({el: '#app'})
</script>
</body>
</html>
注冊(cè)組件步驟解析
1、Vue.extend():
調(diào)用Vue.extend()創(chuàng)建的是一個(gè)組件構(gòu)造器。
通常在創(chuàng)建組件構(gòu)造器時(shí),傳入template代表我們自定義組件的模板。該模板就是在使用到組件的地方,要顯示的HTML代碼。
2、Vue.component():
調(diào)用Vue.component()是將剛才的組件構(gòu)造器注冊(cè)為一個(gè)組件,并且給它起一個(gè)組件的標(biāo)簽名稱。
所以需要傳遞兩個(gè)參數(shù):
1、注冊(cè)組件的標(biāo)簽名。2、組件構(gòu)造器。
3、組件必須掛載在某個(gè)Vue實(shí)例下,否則它不會(huì)生效。
全局組件和局部組件
上述舉的代碼案例是全局組件,那么什么是全局組件和局部組件呢?
全局組件在任何vue管理的容器中都可以使用,但是局部組件只有在指定被管理的容器中才能夠使用。
<body>
<div id="app"><cpn></cpn><cpn></cpn><cpn></cpn>
</div>
<div id="app2"><cpn></cpn>
</div>
<script src="../js/vue.js"></script>
<script>//1.創(chuàng)建組件構(gòu)造器const cpnC = Vue.extend({template: `<div><h2>我是標(biāo)題</h2><p>我是內(nèi)容</p></div>`})//2.注冊(cè)組件(全局組件,意味著可以在多個(gè)Vue的實(shí)例下面使用)// Vue.component('cpn',cpnC)const app = new Vue({el: '#app',})const app2 = new Vue({el: '#app2',//局部組件components: {cpn: cpnC}})
</script>
</body>
局部組件是直接掛載在指定vue下面。
注冊(cè)組件語(yǔ)法糖
在上述注冊(cè)組件的方式,可能會(huì)有些繁瑣,Vue為了簡(jiǎn)化這個(gè)過(guò)程,提供了注冊(cè)的語(yǔ)法糖,主要是省去了調(diào)用Vue.extend()的步驟,而是可以直接使用一個(gè)對(duì)象來(lái)替代。
components: {cpn1: {template: `<div><h2>標(biāo)題1</h2><p>內(nèi)容1</p></div> `}}
3、父組件和子組件
在組件和組件之間存在層級(jí)關(guān)系,而其中非常重要的關(guān)系就是父子組件的關(guān)系
<script>//1、創(chuàng)建第一個(gè)組件構(gòu)造器const cpnC1 = Vue.extend({template: `<div><h2>標(biāo)題1</h2><p>內(nèi)容1</p></div>`})//1、創(chuàng)建第二個(gè)組件構(gòu)造器const cpnC2 = Vue.extend({template: `<div><h2>標(biāo)題2</h2><p>內(nèi)容2</p><cpn1></cpn1></div>`,components: {cpn1: cpnC1}})const app = new Vue({el: '#app',data: {message: '你好啊',},components: {cpn2: cpnC2}})
</script>
其中,cpnC2是cpnC1的父組件,子組件注冊(cè)在父組件中。
組件不可以直接訪問(wèn)Vue實(shí)例中的數(shù)據(jù)
組件是一個(gè)單獨(dú)功能模塊的封裝,這個(gè)模塊有屬于自己的HTML模塊,也應(yīng)該有屬于自己的數(shù)據(jù)data。
組件對(duì)象也有一個(gè)data屬性(也可以有methods等屬性),只是這個(gè)data屬性必須是一個(gè)函數(shù),而且這個(gè)函數(shù)返回一個(gè)對(duì)象,對(duì)象內(nèi)部保存著數(shù)據(jù)。
4、父子組件通信
子組件是不能引用父組件或者Vue實(shí)例的數(shù)據(jù)的。但是,在開(kāi)發(fā)中,往往一些數(shù)據(jù)確實(shí)需要從上層傳遞到下層:
比如在一個(gè)頁(yè)面中,我們從服務(wù)器請(qǐng)求到了很多數(shù)據(jù),其中一部分?jǐn)?shù)據(jù),并非是我們整個(gè)頁(yè)面的大組件來(lái)展示的,而是需要下面的子組件進(jìn)行展示。這個(gè)時(shí)候,并不會(huì)讓子組件再次發(fā)送一個(gè)網(wǎng)絡(luò)請(qǐng)求,而是直接讓父組件將數(shù)據(jù)傳遞給子組件。
如何進(jìn)行父子組件間的通信呢?Vue官方提到:
1、通過(guò)props向子組件傳遞數(shù)據(jù)
2、通過(guò)事件向父組件發(fā)送消息
父級(jí)向子級(jí)傳遞
在組件中,使用選項(xiàng)props來(lái)聲明需要從父級(jí)接收到的數(shù)據(jù)。
props的值有兩種方式:
方式一:字符串?dāng)?shù)組,數(shù)組中的字符串就是傳遞時(shí)的名稱。
方式二:對(duì)象,對(duì)象可以設(shè)置傳遞時(shí)的類型,也可以設(shè)置默認(rèn)值等。
當(dāng)需要對(duì)props進(jìn)行類型等驗(yàn)證時(shí),就需要對(duì)象寫(xiě)法。
驗(yàn)證都支持以下數(shù)據(jù)類型:
- String
- Number
- Boolean
- Array
- Object
- Date
- Function
- Symbol
子級(jí)向父級(jí)傳遞
當(dāng)子組件需要向父組件傳遞數(shù)據(jù)時(shí),就要用到自定義事件了,之前學(xué)習(xí)的v-on不僅僅可以用于監(jiān)聽(tīng)DOM事件,也可以用于組件間的自定義事件。
自定義事件的流程:
- 在子組件中,通過(guò)$emit()來(lái)觸發(fā)事件
- 在父組件中,通過(guò)v-on來(lái)監(jiān)聽(tīng)子組件事件
父子組件的訪問(wèn)方式:$children
有時(shí)候我們需要父組件直接訪問(wèn)子組件,子組件直接訪問(wèn)父組件,或者是子組件訪問(wèn)根組件。
- 父組件訪問(wèn)子組件:使用$children
- 父組件訪問(wèn)子組件:使用$refs
- 子組件訪問(wèn)父組件:使用$parent
父訪問(wèn)子
$children使用:
<body>
<div id="app"><cpn></cpn><button @click="btnClick">按鈕</button>
</div><template id="cpn"><div>我是子組件</div>
</template>
<script src="../js/vue.js"></script>
<script>const app = new Vue({el: '#app',data: {message: '你好啊',},methods: {btnClick() {console.log(this.$children);this.$children[0].showMessage();}},components: {cpn: {template: '#cpn',methods: {showMessage() {console.log('showMessage');}}}}})
</script>
</body>
$refs使用:
<body>
<div id="app"><cpn></cpn><cpn ref="aaa"></cpn><button @click="btnClick">按鈕</button>
</div><template id="cpn"><div>我是子組件</div>
</template>
<script src="../js/vue.js"></script>
<script>const app = new Vue({el: '#app',data: {message: '你好啊',},methods: {btnClick() {console.log(this.$refs.aaa.name);}},components: {cpn: {template: '#cpn',data() {return {name: '我是子組件的name' }},methods: {showMessage() {console.log('showMessage');}}}}})
</script>
</body>
$refs是一個(gè)對(duì)象類型,默認(rèn)是一個(gè)空的對(duì)象
子訪問(wèn)父
$parent使用:
<body>
<div id="app"><cpn></cpn>
</div><template id="cpn"><div><h2>我是cpn組件</h2><ccpn></ccpn></div>
</template>
<template id="ccpn"><div><h2>我是子組件</h2><button @click="btnClick">按鈕</button></div>
</template>
<script src="../js/vue.js"></script>
<script>const app = new Vue({el: '#app',data: {message: '你好啊',},components: {cpn: {template: '#cpn',data() {return {name: '我是cpn組件的name'}},components: {ccpn: {template: '#ccpn',methods: {btnClick() {console.log(this.$parent);console.log(this.$parent.name);}}}}},}})
</script>
</body>
$root使用:
<body>
<div id="app"><cpn></cpn>
</div><template id="cpn"><div><h2>我是cpn組件</h2><ccpn></ccpn></div>
</template>
<template id="ccpn"><div><h2>我是子組件</h2><button @click="btnClick">按鈕</button></div>
</template>
<script src="../js/vue.js"></script>
<script>const app = new Vue({el: '#app',data: {message: '你好啊',},components: {cpn: {template: '#cpn',data() {return {name: '我是cpn組件的name'}},components: {ccpn: {template: '#ccpn',methods: {btnClick() {console.log(this.$root);console.log(this.$root.message);}}}}},}})
</script>
</body>
總結(jié)
以上是生活随笔為你收集整理的第三天:Vue的组件化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 基于Vue开发的购物车案例
- 下一篇: 初学MyBatis-Plus