一 什么是生命周期鉤子片橡?
生命周期鉤子是在Vue對象生命周期的某個階段執(zhí)行的已定義方法。從初始化開始到它被破壞時逆趋,對象都會遵循不同的生命階段哮伟。
我們可以使用生命周期鉤子在Vue對象生命周期的不同階段添加我們的自定義代碼。它將幫助我們控制在DOM中創(chuàng)建對象時創(chuàng)建的流程陈肛,以及更新和刪除對象揍鸟。
beforeCreate
Vue對象用新方法實例化。它創(chuàng)建一個Vue類的對象來處理DOM元素。對象的這個生命階段可以通過beforeCreated 掛鉤來訪問 阳藻。我們可以在這個鉤子中插入我們的代碼晰奖,在對象初始化之前執(zhí)行。
Created(具有默認特性的對象)
在這個生命階段腥泥,對象及其事件完全初始化匾南。 created 是訪問這個階段并編寫代碼的鉤子。
beforeMount(對象在DOM中適合形狀)
這個鉤子被調(diào)用 beforeMounted蛔外。在這個階段蛆楞,它檢查是否有任何模板可用于要在DOM中呈現(xiàn)的對象。如果沒有找到模板夹厌,那么它將所定義元素的外部HTML視為模板豹爹。
Mounted(DOM已準備就緒并放置在頁面內(nèi))
一旦模板準備就緒。它將數(shù)據(jù)放入模板并創(chuàng)建可呈現(xiàn)元素矛纹。用這個新的數(shù)據(jù)填充元素替換DOM元素臂聋。這一切都發(fā)生在mounted鉤子上。
beforeUpdate(更改已完成或南,但尚未準備好更新DOM)
在外部事件/用戶輸入beforeUpdate發(fā)生更改時孩等,此鉤子即 在反映原始DOM元素的更改之前被觸發(fā)。
Updated(在DOM中呈現(xiàn)的更改)
然后采够,通過實際更新DOM對象并觸發(fā)updated肄方,屏幕上的變化得到呈現(xiàn) 。
beforeDestroy(對象準備死掉)
就在Vue對象被破壞并從內(nèi)存中釋放之前吁恍, deforeDestroy 鉤子被觸發(fā)扒秸,并允許我們在其中處理我們的自定義代碼。
Destroyed(對象停止并從內(nèi)存中刪除)
該 destroyed 鉤子被成功運行銷毀對象上調(diào)用冀瓦。
<!DOCTYPE html>
<html>
<head>
<title>鉤子函數(shù)</title>
<meta charset="utf-8">
<script src="./lib/vue.js"></script>
<body>
<div id="app">
<p>{{ message }}</p>
<input type="button" @click="change" value="更新數(shù)據(jù)" />
<input type="button" @click="destroy" value="銷毀" />
</div>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
message : "Welcome Vue"
},
methods:{
change() {
this.message = 'Datura is me';
},
destroy() {
app.$destroy();
}
},
beforeCreate: function () {
console.group('beforeCreate 創(chuàng)建前狀態(tài)===============》');
console.log("%c%s", "color:red","el : " + this.$el); //undefined
console.log("%c%s", "color:red","data : " + this.$data); //undefined
console.log("%c%s", "color:red","message: " + this.message);//undefined
},
created: function () {
console.group('created 創(chuàng)建完畢狀態(tài)===============》');
console.log("%c%s", "color:red","el : " + this.$el); //undefined
console.log("%c%s", "color:green","data : " + this.$data); //[object Object] => 已被初始化
console.log("%c%s", "color:green","message: " + this.message); //Welcome Vue => 已被初始化
},
beforeMount: function () {
console.group('beforeMount 掛載前狀態(tài)===============》');
console.log("%c%s", "color:green","el : " + (this.$el)); //已被初始化
console.log(this.$el); // 當前掛在的元素
console.log("%c%s", "color:green","data : " + this.$data); //已被初始化
console.log("%c%s", "color:green","message: " + this.message); //已被初始化
},
mounted: function () {
console.group('mounted 掛載結(jié)束狀態(tài)===============》');
console.log("%c%s", "color:green","el : " + this.$el); //已被初始化
console.log(this.$el);
console.log("%c%s", "color:green","data : " + this.$data); //已被初始化
console.log("%c%s", "color:green","message: " + this.message); //已被初始化
},
beforeUpdate: function () {
alert("更新前狀態(tài)");
console.group('beforeUpdate 更新前狀態(tài)===============》'); //這里指的是頁面渲染新數(shù)據(jù)之前
console.log("%c%s", "color:green","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:green","data : " + this.$data);
console.log("%c%s", "color:green","message: " + this.message);
alert("更新前狀態(tài)2");
},
updated: function () {
console.group('updated 更新完成狀態(tài)===============》');
console.log("%c%s", "color:green","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:green","data : " + this.$data);
console.log("%c%s", "color:green","message: " + this.message);
},
beforeDestroy: function () {
console.group('beforeDestroy 銷毀前狀態(tài)===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message);
},
destroyed: function () {
console.group('destroyed 銷毀完成狀態(tài)===============》');
console.log("%c%s", "color:red","el : " + this.$el);
console.log(this.$el);
console.log("%c%s", "color:red","data : " + this.$data);
console.log("%c%s", "color:red","message: " + this.message)
}
})
</script>
</body>
</html>
點擊更新數(shù)據(jù)
點擊銷毀之后此實例已不存在
二 組件之間傳值
組件:組件是可復(fù)用的 Vue 實例伴奥,且?guī)в幸粋€名字,每個組件必須只有一個根元素翼闽,data必須是一個函數(shù)拾徙。
因為組件是可復(fù)用的 Vue 實例,所以它們與 new Vue 接收相同的選項感局,例如 data尼啡、computed、watch询微、methods 以及生命周期鉤子等崖瞭。僅有的例外是像 el 這樣根實例特有的選項。
父子組件的關(guān)系可以總結(jié)為 prop 向下傳遞撑毛,事件向上傳遞书聚。父組件通過 prop 給子組件下發(fā)數(shù)據(jù),子組件通過事件給父組件發(fā)送消息,如下圖所示:
1.父組件通過Prop向子組件傳遞數(shù)據(jù)
Prop 是你可以在組件上注冊的一些自定義特性雌续。當一個值傳遞給一個 prop 特性的時候斩个,它就變成了那個組件實例的一個屬性⊙倍牛可以用一個 props 選項將需要傳遞的數(shù)據(jù)包含在該組件可接受的 prop 列表中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<counter :step1="2"></counter>
</div>
<script src="./lib/vue.js"></script>
<script>
Vue.component('counter',{
template:`<button @click="plusHandle">當前計數(shù)值: {{count}}</button>` ,
data(){
return {
count:1,
step:1
}
},
methods: {
plusHandle(){
this.count+=this.step1
}
},
props:['step1']
})
var app=new Vue({
el:'#app',
})
</script>
</body>
</html>
2.子組件向父組件傳值 使用事件派發(fā)
在子組件內(nèi)部使用this.$emit派發(fā)事件
在父組件中使用@(v-on)綁定事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<h5>當前計數(shù)器的值為:{{c}}</h5>
<counter @plusadd="plusAddHandle" :step1="2"></counter>
</div>
<script src="./lib/vue.js"></script>
<script>
Vue.component('counter',{
template:`<button @click="plusHandle">當前計數(shù)值: {{count}}</button>` ,
data(){
return {
count:0,
step:1
}
},
methods: {
plusHandle(){
this.count+=this.step1;
this.$emit('plusadd',this.count);
}
},
props:['step1']
})
var app=new Vue({
el:'#app',
data:{
c:0,
},
methods: {
plusAddHandle(params){
this.c=params;
}
}
})
</script>
</body>
</html>
3.非父子組件之間的數(shù)據(jù)傳遞
為了解決非父子組件之間的傳值問題受啥,引入事件總線(EventBus)
在vue中使用一個空白的Vue對象作為一個EventBus,用來做事件的監(jiān)聽和派發(fā)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>動態(tài)組件</title>
<style>
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
.nav {
background-color: deeppink;
padding: 1.5rem 1rem;
height: 60px;
}
.nav ul {
margin: 0;
padding: 0;
}
.nav ul li {
float: left;
margin: 1.5rem;
list-style: none;;
}
.nav a {
color: #fff;
cursor: pointer;
}
.nav a.cur {
color: greenyellow;
}
.product {
border-bottom: 1px solid #ccc;
padding: 0.2rem 0.5rem;
}
</style>
</head>
<body>
<div id="app">
<navbar @pagchange="changePageHandle"></navbar>
<component :is="currentPage"></component>
</div>
<script src="./lib/vue.js"></script>
<script>
// 事件總線
// 為了解決非父子組件之間的傳值問題,引入事件總線
// 在vue中使用一個空白的Vue對象作為一個EventBus,用來做事件的監(jiān)聽和派發(fā)
const Nav = {
template: `
<div class="nav">
<ul>
<li><a :class="this.selIndex==0? 'cur': ''" @click="navClick(0, 'Home')">首頁</a></li>
<li><a :class="this.selIndex==1? 'cur': ''" @click="navClick(1, 'List')">商品列表頁</a></li>
<li><a :class="this.selIndex==2? 'cur': ''" @click="navClick(2, 'Cart')">購物車【{{cartCount}}】</a></li>
<li><a :class="this.selIndex==3? 'cur': ''" @click="navClick(3, 'Us')">關(guān)于我們</a></li>
</ul>
</div>
`,
data() {
return {
selIndex: 0,
cartCount: 0
}
},
methods: {
navClick(index, page) {
this.$emit('pagchange', page); // 子組件傳值到父組件
this.selIndex = index
}
},
created() {
this.$eventBus.$on('addToCartEvent', (id) => {
console.log(id);
console.log(this);
this.cartCount += 1;
})
}
}
const Home = {
template: `
<div>
<h1>我是首頁</h1>
</div>
`
}
const List = {
template: `
<div>
<div v-for="item in products" class="product">
<h3>{{item.name}}</h3>
<p>{{item.price}}<button @click="addToShopCart(item.id)">加入購物車</button></p>
</div>
</div>
`,
data() {
return {
products: [{
id: 1,
name: 'iphone18',
price: 19999,
}, {
id: 2,
name: 'vivo 32',
price: 5200
}, {
id: 3,
name: 'redmi 10',
price: 3000,
}]
}
},
methods: {
addToShopCart(id) {
this.$eventBus.$emit('addToCartEvent', id); // 使用$eventBus對象派發(fā)一個事件
}
}
}
const Cart = {
template: `
<div>
<h1>我是購物車</h1>
</div>
`
}
const Us = {
template: `
<div>
<h1>關(guān)于我們</h1>
</div>
`
}
var $eventBus = new Vue(); // 使用一個空白的VUE實例作為中間媒介
Vue.prototype.$eventBus = $eventBus; // 此種定義的屬性可以在實例中進行訪問
var app = new Vue({
el: '#app',
components: {
navbar: Nav,
Home,
List,
Cart,
Us
},
data: {
currentPage: 'Home'
},
methods: {
changePageHandle(page) {
this.currentPage = page;
}
}
})
</script>
</body>
</html>