1.组件的生命周期
1.1 生命周期 & 生命周期函数
生命周期(Life Cycle) 是指一个组件从创建 -> 运行 -> 销毁的整个阶段,强调的是一个时间段。
生命周期函数:是由 vue 框架提供的内置函数,会伴随着组件的生命周期,自动按次序执行。
注意:生命周期强调的是时间段,生命周期函数强调的是时间点
1.2 组件生命周期函数的分类
1.3 生命周期图示
1.4 beforeCreate
beforeCreate:组件的 props、data、methods 尚未被创建,都处于不可用的状态
App.vue 内容如下:
<template>
<div id="app">
<div>{{ num }}</div>
<button @click="show">按钮</button>
</div>
</template>
<script>
export default{
data(){
return{
num : 1
}
},
methods:{
show(){
console.log('调用了 show 方法')
}
},
beforeCreate(){
console.log(this.num)
this.show()
}
}
</script>
由于组件的 props、data、methods 尚未被创建,都处于不可用的状态,所以 num 打印出来为 undefined,show 方法找不到。
1.5 created
created:组件的 props、data、methods 已经创建完毕,都处于可用的状态,但模板结构尚未生成
App.vue 内容如下:
<template>
<div id="app">
<div>{{ num }}</div>
<button @click="show">按钮</button>
</div>
</template>
<script>
export default{
data(){
return{
num : 1
}
},
methods:{
show(){
console.log('调用了 show 方法')
}
},
created(){
console.log(this.num)
this.show()
const btn = document.querySelector('button')
console.log(btn) // 无法获取
}
}
</script>
由于组件的 props、data、methods 已经创建完毕,都处于可用的状态,但模板结构尚未生成,所以 num 打印出来为 1,show 方法正常使用,但无法获取到 dom 结构,所以为 null。
由于有数据,但模板还未创建。所以该函数常用功能是:请求服务器数据,并将数据转存到 data 中,供 template 模板渲染的时候使用。
1.6 beforeMount
beforeMount:基本和 created 类似,所以将该刚才 created 换成 beforeMount,执行结果是一致的。
他们的不同点在所处的时间段不一样:
create:HTML结构未编译beforeMount:HTML结构编译完成
且两者均无法调用 DOM 结构,因为模板还没有被渲染。
1.7 mounted
mounted:已经把内存中的 HTML 成功渲染,即:可以使用 DOM 结构了
App.vue 内容如下:
<template>
<div id="app">
<div>{{ num }}</div>
<button @click="show">按钮</button>
</div>
</template>
<script>
export default{
data(){
return{
num : 1
}
},
methods:{
show(){
console.log('调用了 show 方法')
}
},
mounted(){
console.log(this.num)
this.show()
const btn = document.querySelector('button')
console.log(btn)
}
}
</script>
所以:mounted 是最早能够操作 DOM 的生命周期函数
1.8 beforeUpdate
beforeUpdate:数据变化时,数据先变化,DOM 结构不变(未被渲染)
App.vue 内容如下:
<template>
<div id="app">
<div class="val">{{ num }}</div>
<button @click="show">按钮</button>
<button @click="add">+1</button>
</div>
</template>
<script>
export default{
data(){
return{
num : 1
}
},
methods:{
show(){
console.log('调用了 show 方法')
},
add(){
this.num+=1
}
},
beforeUpdate(){
const val = document.querySelector('.val')
this.show()
console.log(val.innerHTML)
console.log(this.num)
}
}
</script>
按下 +1 按钮后,结果如下:
按下之后数据肯定会发生变化,所以该函数的 this.num 变成了 2,但由于模板结构没有被重新渲染,所以 DOM 结构的 innerHTML 没有变化。
1.9 updated
updated:已经根据最新的数据,DOM 结构重新渲染
App.vue 内容如下:
<template>
<div id="app">
<div class="val">{{ num }}</div>
<button @click="show">按钮</button>
<button @click="add">+1</button>
</div>
</template>
<script>
export default{
data(){
return{
num : 1
}
},
methods:{
show(){
console.log('调用了 show 方法')
},
add(){
this.num+=1
}
},
beforeUpdate(){
const val = document.querySelector('.val')
this.show()
console.log(val.innerHTML)
console.log(this.num)
}
}
</script>
按下 +1 按钮后,结果如下:
数据和 DOM 结构被重新渲染,所以值都是 2。
1.10 组件销毁(略)
beforeDestroy 和 destroy 都是销毁阶段的生命周期函数,没什么特别好说的,一般也不会用到。
2. 组件之间的数据共享
2.1 组件之间的关系
在项目开发中,组件之间的最常见的关系分为如下两种:
- 父子关系
- 兄弟关系
如上图所示:
- A 与 B,A 与 C 之间就是父子关系
- A 与 D,E 与 F,B 与 E 之间就是兄弟关系
即,有直接联系的就是父子关系,否则可认为是兄弟关系
2.2 父子组件之间的数据共享
父子组件之间的数据共享又分为:
-
父 -> 子 共享数据
-
子 -> 父 共享数据
2.2.1 父 -> 子
父组件向子组件共享数据需要使用自定义属性。
逻辑:
- 父组件有要传输给子组件的数据
- 联结方式:用
v-bind绑定自定义属性,值就是要传输的数据 - 子组件要定义自定义属性
父组件:
<template>
<div id="app">
<Son :msg="message" :user="userinfo"></Son>
</div>
</template>
<script>
import Son from '@/components/Son.vue'
export default{
components:{
Son
},
data(){
return{
message: 0,
userinfo:{name:'zs','age':18}
}
}
}
</script>
子组件:
<template>
<div id="Son">
<h2>子组件</h2>
<div>父给子的 msg 是{{ msg }}</div>
<div>父给子的 user 是{{ user }}</div>
</div>
</template>
<script>
export default {
props: ['msg','user']
}
</script>
<style>
</style>
2.2.2 子 -> 父
子组件向父组件共享数据使用自定义事件。
逻辑:
-
子组件要有自定义的事件和要发送的数据
this.$emit('事件名称', 要发送的数据) -
联结方式:通过触发自定义事件进行联结,这个事件相当于触发条件,类似于:
click、keyup,所以后面可以跟个函数 -
父组件中可以根据自定义事件的函数来取到子组件的值
子组件:
<template>
<div id="Son">
<h2>子组件</h2>
<button @click="add" >+1</button>
</div>
</template>
<script>
export default {
data(){
return {
num: 0
}
},
methods:{
add(){
this.num++
this.$emit('trans', this.num)
}
}
}
</script>
<style>
</style>
父组件:
<template>
<div id="app">
<Son @trans="getNum"></Son>
<div>{{ count }}</div>
</div>
</template>
<script>
import Son from '@/components/Son.vue'
export default{
components:{
Son
},
data(){
return{
count:0
}
},
methods:{
getNum(val){
this.count = val
}
}
}
</script>
2.3 兄弟组件之间的数据共享
在 vue2.x 中,兄弟组件之间数据共享的方案是 EventBus。
EventBus 的使用步骤:
-
创建
eventBus.js模块,并向外共享一个Vue的实例对象 -
在数据发送方,调用
bus.$emit('事件名称', 要发送的数据)方法触发自定义事件 -
在数据接收方,调用
bus.$on('事件名称', 事件处理函数)方法注册一个自定义事件
eventBus.js 模块:
import Vue from 'vue'
// 向外共享 Vue 的实例对象
export default new Vue()
发送方:
<template>
<div id="left">
<h2>左组件</h2>
<button @click="sendMsg">发送</button>
</div>
</template>
<script>
import bus from './eventBus.js'
export default {
data(){
return{
msg:'hello, right!'
}
},
methods:{
sendMsg(){
bus.$emit('share', this.msg)
}
}
}
</script>
<style>
</style>
接收方:
<template>
<div id="right">
<h2>右组件</h2>
<div>{{ leftMsg }}</div>
</div>
</template>
<script>
import bus from './eventBus.js'
export default {
data(){
return{
leftMsg:'9'
}
},
created(){
bus.$on('share', val => {
this.leftMsg = val
})
}
}
</script>
<style>
</style>
如有错误,敬请指正,欢迎交流🤝,谢谢♪(・ω・)ノ