1. 什么是組件
組件化就是把頁面拆分成一塊塊的唠梨,后期維護(hù)很簡(jiǎn)單
組件其實(shí)也是vue的實(shí)例洞坑,組件是可以反復(fù)使用的vue實(shí)例
- 全局注冊(cè)組件
就是把組件用Vue.component()注冊(cè)
<body>
<div id="app">
<!-- 3添履、使用組件 -->
<my-header></my-header>
</div>
</body>
<script src="vue.js"></script>
<script>
// 全局注冊(cè)組件
// 1、定義組件
const MyHeader = {
template: `<header>頭部</header>`,
}
// 2、全局注冊(cè)組件
Vue.component('my-header', MyHeader)
new Vue({
el: '#app'
})
</script>
- 局部注冊(cè)組件
就是把組件注冊(cè)在某個(gè)Vue實(shí)例中,用components:{}注冊(cè)
<body>
<div id="app">
<!-- 3双炕、使用組件 -->
<my-header></my-header>
</div>
</body>
<script src="vue.js"></script>
<script>
// 局部注冊(cè)組件
// 1、定義組件
const MyHeader = {
template: `<header>頭部</header>`,
}
new Vue({
el: '#app',
// 2撮抓、局部注冊(cè)組件
components: {
'my-header': MyHeader
}
})
</script>
2. 組件間的傳值
1. 父組件給子組件傳值
- 父組件在調(diào)用子組件的地方需要添加一個(gè)屬性<my-content test = "測(cè)試"/>
- 屬性的值”測(cè)試”就是你要傳遞給子組件的值
- 在子組件定義的地方添加一個(gè)選項(xiàng)叫props:{}
- 在props里放父組件傳遞的屬性名妇斤,也就是test就可以了,要注意的是丹拯,如果父組件傳遞給子組件的值是變量站超,Number或者布爾值就需要v-bind了!props內(nèi)存放值有兩種方式
- 第一種:數(shù)組:props:[‘test’],之后就可以在子組件中使用了
- 第二種:對(duì)象:props:{test:String}乖酬,這是寫法一用來驗(yàn)證傳遞數(shù)據(jù)的有效性死相,因?yàn)楦缸咏M件可能不是一個(gè)人寫的,如果數(shù)據(jù)類型不對(duì)剑刑,就會(huì)警告,可以及時(shí)調(diào)整双肤。
- Props:{test:{type:String施掏,default:’默認(rèn)值’}}這是第二種寫法,既要驗(yàn)證數(shù)據(jù)類型也要設(shè)置默認(rèn)值茅糜,如果默認(rèn)值是對(duì)象或者函數(shù)七芭,則默認(rèn)值需要時(shí)一個(gè)有返回值的函數(shù)function () {return {}}
<body>
<div id="app">
<!-- <my-content test = "測(cè)試" :count="100" :flag="true" :tip="tip"/> -->
<my-content :count="100" :flag="true" :tip="tip"/>
</div>
</body>
<template id="content">
<div>
我這里是內(nèi)容區(qū)域 --- {{ test }} -- {{ count }} --- {{ flag }} --- {{ tip }}
</div>
</template>
<script src="vue.js"></script>
<script>
// 組件的名稱不能和模板的id同名
const Content = {
template: '#content',
// props: ['test', 'count', 'flag', 'tip']
// props: {
// test: String,
// count: Number,
// flag: Boolean,
// tip: String
// }
props: {
test: {
type: String,
default: '測(cè)試數(shù)據(jù)了' // 如果父組件有這個(gè)屬性,那么就用父組件的值蔑赘,沒有這個(gè)屬性狸驳,直接使用這個(gè)值
}
}
}
new Vue({
el: '#app',
data: {
tip: '提示'
},
components: {
'my-content': Content
}
})
</script>
2. 子組件給父組件傳值
- 子組件給父組件傳值時(shí),需要在父組件調(diào)用子組件的地方缩赛,給它綁定一個(gè)自定義事件耙箍,事件后面不要加(),例:<my-content @myevent="getData"/>
- 在父組件選項(xiàng)methods中使用這個(gè)getData(val){}酥馍,其中參數(shù)val是默認(rèn)傳遞的辩昆,傳遞的就是子組件傳遞給父組件的值
- 而在子組件如何傳遞呢?如下旨袒!
- 在子組件種汁针。你可以通過生命周期的鉤子函數(shù)术辐,也可以是組件自己的事件去觸發(fā)父組件中的自定義事件myevent,使用固定語法emit來傳遞例:this.$emit('myevent', 10000)施无,這樣就把名字為myevent的參數(shù)名辉词,參數(shù)為10000的整個(gè)值廣播出去了,父組件只要接受myevent就可以了猾骡!
<body>
<div id="app">
<my-content @myevent="getData"/>
</div>
</body>
<template id="content">
<div>
我這里是內(nèi)容區(qū)域
</div>
</template>
<script src="vue.js"></script>
<script>
/**
* 父組件調(diào)用子組件的地方瑞躺,給他綁定一個(gè)自定義的事件, 事件不要加()
* <my-content @myevent="getData"/>
* 在父組件選項(xiàng)methods中實(shí)現(xiàn)此事件,默認(rèn)參數(shù)為你將從子組件得到的值
* methods: {
getData (val) { // val為從子組件中獲取到的值
console.log(val)
}
},
在子組件中卓练,可以是生命周期鉤子函數(shù)隘蝎,也可以是組件自己的事件 去 觸發(fā) 父組件中的自定義事件
this.$emit('myevent', 10000)
**/
const Content = {
template: '#content',
mounted () {
this.$emit('myevent', 10000)
}
}
new Vue({
el: '#app',
data: {},
methods: {
getData (val) { // val為從子組件中獲取到的值
console.log(val)
}
},
components: {
'my-content': Content
}
})
</script>
3. 非父子組件間傳值
- 中央事件總線傳值const bus = new Vue()他就類似于一個(gè)快遞員的身份,需要確保數(shù)據(jù)有人接受的情況下襟企,就可以接受參數(shù)然后傳遞參數(shù)給需要的人嘱么!
- 第一步:給需要這個(gè)參數(shù)的組件,定義bus.$on(‘參數(shù)名’,(val)={對(duì)收到的val做手腳})顽悼,一般寫在鉤子函數(shù)mounted中曼振。還要注意這里盡量使用箭頭函數(shù)避免this指向出現(xiàn)問題
- 第二步:在確定了有接受的組件時(shí),就可以給要發(fā)送的組件設(shè)置了蔚龙!在發(fā)送參數(shù)的組建中的methods中添加一個(gè)自定義函數(shù)冰评,在里面定義bus.emit(‘參數(shù)名’,參數(shù))木羹,當(dāng)觸發(fā)了bus.emit時(shí)甲雅,像外廣播了一個(gè)參數(shù)名,然后另一個(gè)組件通過bus.$on接收到了參數(shù)名相同的參數(shù)值坑填,這樣就形成了非父子組件之間的值傳遞
<body>
<div id="app">
<my-list></my-list>
<my-count></my-count>
</div>
</body>
<template id="list">
<ul>
<li>111<button @click="add">+1</button></li>
<li>222<button @click="add">+1</button></li>
<li>333<button @click="add">+1</button></li>
<li>444<button @click="add">+1</button></li>
<li>555<button @click="add">+1</button></li>
</ul>
</template>
<template id="count">
<div>
總量是:{{ num }}
</div>
</template>
<script src="vue.js"></script>
<script>
/**
* 非父子組件傳值 ---- 兄弟組件傳值 (郵差與信的故事)
* ------------------ 中央事件總線傳值 1. const bus = new Vue()
*
* 先要確保 收信 的那個(gè)人是存在的
* 然后寫信的人 寫信 給郵差
* 郵差給送
*
* // 此處一定要注意this指向抛人,可以使用 =>
* 2.在接收端通過 bus.$on('收信信號(hào)', function (val) {
*
* })
*
* 3.在發(fā)送端通過 bus.$emit('收信信號(hào)', val)
* */
const bus = new Vue()
const List = {
template: '#list',
methods: {
add () {
bus.$emit('count-event', 1)
}
}
}
const Count = {
template: '#count',
data () {
return {
num: 0
}
},
mounted () { // 一般情況下接收都使用 生命周期鉤子函數(shù)
bus.$on('count-event', (val) => { // 此處一定要注意this指向脐瑰,可以使用 =>
console.log(val)
this.num += val
})
}
}
new Vue({
el: '#app',
components: {
'my-list': List,
'my-count': Count
}
})
</script>
4. 動(dòng)態(tài)組件
<component is="組件名稱"></component>
概述:讓當(dāng)前畫面在幾個(gè)組件中來回切換妖枚,類似你的手機(jī)屏幕,同一個(gè)屏幕可以打開不同的app顯示不同的內(nèi)容苍在。
使用:一般在頁面只寫一個(gè)類似于<component :is="tem"></component>的組件绝页,頁面有按鈕操控tem在data中的值,一旦改變值寂恬,在components中注冊(cè)名稱為改變得值得組件续誉,就可以在頁面中顯示出所對(duì)應(yīng)的組件了。
但是隨之的問題就出現(xiàn)了初肉,每次切換回前一個(gè)組件時(shí)屈芜,上次的操作就會(huì)被清除,所以需要用keep-alive把components包裹起來
keep-alive:保留組件的狀態(tài),避免組件的重新渲染 --- 類似于手機(jī)軟件使用中按了home鍵之后應(yīng)用程序的狀態(tài)
但是有些時(shí)候就是需要切換回頁面數(shù)據(jù)清除井佑,所以只需要給keep-alive添加一個(gè)include屬性就可以了属铁,后面的屬性值是在組件注冊(cè)時(shí)定義的名稱name的值。添加上的組件就會(huì)保存之前的信息躬翁,而沒有添加的組件name就會(huì)數(shù)據(jù)消失
動(dòng)態(tài)組件生命周期鉤子函數(shù)
每個(gè)組件都會(huì)有兩個(gè)鉤子函數(shù)activated()---正在用的焦蘑,deactivated()---后臺(tái)的,如果該組件在keep-alive的include內(nèi)盒发,那么該組件再被切換時(shí)例嘱,會(huì)觸發(fā)deactivated()鉤子函數(shù)類似于后臺(tái)運(yùn)行,在使用時(shí)會(huì)觸發(fā)activated()鉤子函數(shù)
<body>
<div id="app">
<button @click="tem='my-a'">AAA</button>
<button @click="tem='my-b'">BBB</button>
<button @click="tem='my-c'">CCC</button>
<keep-alive include="a,b">
<component :is="tem"></component>
</keep-alive>
</div>
</body>
<template id="acom">
<div>
<input type="text" placeholder="a組件">
</div>
</template>
<template id="bcom">
<div>
<input type="text" placeholder="b組件">
</div>
</template>
<template id="ccom">
<div>
<input type="text" placeholder="c組件">
</div>
</template>
<script src="vue.js"></script>
<script>
/**
* keep-alive
* 保留組件的狀態(tài)宁舰,避免組件的重新渲染 --- 類似于手機(jī)軟件使用中按了home鍵之后應(yīng)用程序的狀態(tài)
* 添加include 可以 只給部分組件保留狀態(tài)拼卵,需要定義組件時(shí)添加name屬性
*
* 每個(gè)組件都會(huì)有 兩個(gè)生命周期鉤子函數(shù)
* activated() 正在用的
* deactivated() 后臺(tái)的
* */
const Acom = {
name: 'a',
template: '#acom',
activated () {
console.log(' a 正在被使用')
},
deactivated () {
console.log(' a 被雪藏了')
}
}
const Bcom = {
name: 'b',
template: '#bcom',
activated () {
console.log(' b 正在被使用')
},
deactivated () {
console.log(' b 被雪藏了')
}
}
const Ccom = {
template: '#ccom',
activated () {
console.log(' c 正在被使用')
},
deactivated () {
console.log(' c 被雪藏了')
}
}
new Vue({
el: '#app',
data: {
tem: 'my-a'
},
components: {
'my-a': Acom,
'my-b': Bcom,
'my-c': Ccom
}
})
</script>