1.生命周期与生命周期函数:
生命周期:指的是一个组件从创建到运行再到销毁的整个阶段。
生命周期函数:Vue提供的内置函数,会在生命周期的过程中自动的按照次序执行。
生命周期强调的是一个时间段,而生命周期函数强调的是时间点。
2.生命周期的阶段:
组件创建阶段、组件运行阶段、组件销毁阶段
3.在各生命周期阶段的解释
组件创建阶段:
一个组件以标签的形式使用时,就会立即创建一个组件实例,new Vue()。在内存中初始化这个组件对应的基本事件和生命周期函数。初始化完成后会立即触发beforeCreate生命周期函数。
beforeCreate阶段:就是初始化组件的Vue实例,此时组件的props/date/methods等还没有被创建,都处于不可用的状态,也就是说props和data里面的数据不能访问,methods里面的方法不能调用。
在beforeCreate生命周期函数之后会初始化props/date/methods。初始化完成后会立即触发created生命周期函数。
created阶段:组件的props/date/methods都已经被创建好了,并且都是可用状态。但是此时的模板结构还没有生成,vm.$el没有创建,不能操作DOM。在这个阶段可以在methods中发起Ajax请求,把请求回来的数据保存在date中,在created里面通过this调用,之后供template模板渲染的时候使用。
在created生命周期函数之后有一个判断,判断是否有el选项,如果有el选项就继续判断是否有template选项。如果没有el选项,就会判断当vm.$mount(el)这个方法被调用的时候,再判断是否有template选项,如果有template选项就编译template选项。如果没有就会把el提供的区域基于数据和模板在内存中去编译生成HTML结构。(通过package.json文件中的"vue-template-compiler"vue模板编译器把.vue文件编译生成JavaScript脚本文件后,交给浏览器去执行。)编译好HTML结构后,会自动触发beforeMount生命周期函数。
beforeMount阶段:将要把内存中编译好的HTML结构渲染到浏览器中,此时浏览器还没有当前组件的DOM结构,只是在内存中,不能操作DOM。
beforeMount执行完后,用内存中编译生成的HTML结构替换el属性指定的DOM元素。之后会自动触发mounted生命周期函数。
mounted阶段:内存中编译好的HTML结构已经在浏览器中渲染完成。可以在此时操作DOM。此时浏览器中已经包含了当前组件的DOM结构。最早操作DOM元素可在此阶段进行。
当进行到mounted阶段说明一个组件已经创建成功,可以供用户去访问。
组件运行阶段:
beforeUpdate阶段:当页面的DOM结构发生变化时,将要根据最新的数据重新渲染页面的DOM结构。此时data里面的数据是最新的,但是页面的dom结构未更新还是旧的。
updated阶段:已经根据最新的数据重新渲染组件的DOM结构。此时data里面的数据是最新的,页面的dom结构也是最新的。此时可以操作最新的DOM。
组件销毁阶段:
beforeDestory阶段:组件将要销毁,此时组件还存在,仍然处于可用的状态。
destory阶段:组件已经被销毁,组件在浏览器中对应的DOM结构已经被移除。
最常用的生命周期函数是:created和mounted。
beforeCreate、created、beforeMount、mounted、beforeDestory、destory生命周期函数在一个组件生命周期里进行1次。
beforeUpdate和updated生命周期函数在一个组件生命周期里可进行0次或n次。
4.代码示例:
Test.vue组件:
<template>
<div class="test-container">
<!-- 根据转存到data里面的图书列表信息,通过books.length将图书的数量渲染出来 -->
<h3 id="myh3">test组件--{{books.length}}本图书</h3>
<p id="ppp">message的值是{{message}}</p>
<button @click="message+='~'">修改messgae的值</button>
</div>
</template>
<script>
export default {
props:['info'],
data() {
return {
message: 'hello,vue.js',
// 将Ajax请求回来的数据转存到data里面 供模版渲染使用
books:[]
}
},
methods: {
show() {
console.log('调用了Test的show方法')
},
// 用原生Ajax发请求拿到图书列表的数据
initBooks() {
const xhr = new XMLHttpRequest()
xhr.addEventListener('load', () => {
const result = JSON.parse(xhr.responseText)
console.log(result)
this.books=result.data
})
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks')
xhr.send()
}
},
// beforeCreate生命周期
// props/ date / methods等还没有被创建,都处于不可用的状态
beforeCreate() {
// console.log(this.info) //报错 Cannot read properties of undefined (reading 'info')"
// console.log(this.message) //undefined
// this.show() //报错 TypeError: this.show is not a function
},
// created生命周期
created() {
// props/ date / methods已经被创建好,都处于可用的状态 此时可以发起Ajax请求拿数据
// console.log(this.info) //你好
// console.log(this.message) //hello,vue.js
// this.show() //调用了Test的show方法
// 调用Ajax请求拿数据的方法
this.initBooks()
// 但是此时组件的模板结构还没有生成,不能操作dom
// const dom = document.querySelector('#myh3')
// console.log(dom) //null
},
// beforeMount生命周期
// 此时浏览器还没有当前组件的DOM结构,只是在内存中,不能操作DOM
beforeMount() {
// console.log('beforeMount') //beforeMount
// const dom = document.querySelector('#myh3')
// console.log(dom) //null
// console.log(this.$el) //undefined
},
// mounted生命周期
// 内存中编译好的HTML结构已经在浏览器中渲染完成。可以在此时操作DOM 最早操作DOM元素可在此阶段进行
mounted() {
// console.log('mounted')
// const dom = document.querySelector('#myh3')
// console.log(dom) //<h3 data-v-dc87507c="" id="myh3">test组件--5本图书</h3>
},
// beforeUpdate生命周期
// 将要根据最新的数据重新渲染页面的DOM结构
beforeUpdate() {
// console.log('beforeUpdate')
// // data里面的数据是最新的,但是页面的dom结构还是旧的
// console.log(this.message) //hello,vue.js~
// const dom = document.querySelector('#ppp')
// console.log(dom.innerHTML) //hello,vue.js
},
// updated生命周期
// 已经根据最新的数据重新渲染组件的DOM结构
updated() {
console.log('updated')
// data里面的数据是最新的,页面的dom结构也是最新的
console.log(this.message) //hello,vue.js~
const dom = document.querySelector('#ppp')
console.log(dom.innerHTML) //hello,vue.js~
},
}
</script>
<style lang="less" scoped>
.test-container{
background-color: pink;
height: 200px;
}
</style>
App.vue根组件:
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
<Test info="你好"></Test>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
import Test from './components/Test.vue'
export default {
name: 'App',
components: {
HelloWorld,
Test
}
}
</script>
<style lang="less">
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>