什么是生命周期呢?
创建、挂载、更新、卸载
等一系列的过程;某一个阶段
,我们可能会想要添加一些属于自己的代码逻辑
(比如组件创建完后就请求一些服务器数据);如何可以知道目前组件正在哪一个过程
呢?Vue给我们操供了组件的生命周期函数
;生命周期函数:
一些钩子函数(回调函数)
,在某个时间会被Vue源码内部进行回调
;知道目前组件正在经历什么阶段
;该生命周期中编写属于自己的逻辑代码了
;生命周期的流程图示(官网):
beforeCreate
:
创造组件实例之前。会回调beforeCreate函数
created
:
beforeCreate回调完成之后, 就会创建组件实例, 组件实例创建完成, 回调created函数;
此钩子的主要应用场景是发送网络请求,事件监听、this.$watch等设置。
beforeMount
:
created回调完成之后,未挂载到虚拟Dom之前被调用;
此时,Vue实例的DOM元素并未真正被替换挂载,但其组件实例的Vue.$el已经得到了内容渲染。
此钩子的主要应用场景是在DOM元素挂载之前进行一些异步操作,如数据异步处理等。
mounted
:
Vue实例DOM已经被渲染并挂载到页面的DOM元素上,挂载完成后,回调mounted函数。
此钩子的主要应用场景是完成一些必须在挂载后进行的异步操作,如元素初始化、事件绑定等,也可以在此获取Dom,操作Dom
beforeUpdate
:
挂载完成后,数据更新后,更改还没有重新渲染组件实例(即更新前的组件实例)之前被调用。
此钩子的主要场景是处理一些数据更新后的异步操作,如获取最新数据等。
updated
:
根据最新数据生成新的VNode, 重新渲染成新的虚拟DOM, 再根据新的虚拟DOM渲染成真实DOM后,此钩子将被调用。
此钩子的主要应用场景是完成DOM更新之后操作,如操作DOM后重新计算元素大小等。
beforeUnmount
:
在组件实例销毁之前被调用,即在组件实例的DOM元素被卸载之前,在组件的父组件或Vue实例销毁之前。
此钩子的主要应用场景包括与组件实例相关的清理操作,如删除定时器、取消事件监听等。
unmounted
:
在组件的DOM元素被卸载之后被调用,此时组件的实例已经被销毁,无法再操作组件实例。
此钩子的主要应用场景包括回收内存和解绑事件监听器等。
来做一个简单的演练,理解各个生命周期函数的执行顺序和应用场景:
(1)直接在App组件中使用除beforeUnmount和unmounted之外的各个生命函数:
<template>
<div id="app">
<h2>{{ message }}-{{ counter }}h2>
<button @click="message='hello app'">修改messagebutton>
<button @click="counter++">+1button>
div>
<div>
<button @click="isShowHome=!isShowHome">显示homebutton>
<Home v-if="isShowHome">Home>
div>
template>
<script>
import Home from "./Home.vue";
export default {
components:{
Home
},
data(){
return{
message:"ada",
counter:0,
isShowHome:true
}
},
// 1.组件被创建之前
beforeCreate(){
console.log("beforecreate");
},
// 2.组件被创建完成(重点掌握)
created(){
console.log("created:组件被创建完成");
console.log("1.发送网络请求,请求数据");
console.log("2.监听eventbus事件");
console.log("3.监听watch数据");
},
// 3.组件中的template准备被挂载(了解)
beforeMount(){
console.log("beforemount");
},
// 4.组件template被挂载:虚拟dom-> 真实dom(重点掌握)
mounted(){
console.log("mounted");
console.log("1.获取虚拟Dom");
console.log("2.使用dom");
},
// 5.数据发生了改变
// 5.1准备更新
beforeUpdate(){
console.log("beforeupdate");
},
// 5.2更新dom
updated(){
console.log("updated");
},
// 6.准备卸载vnode->dom元素
// 6.1卸载之前
beforeUnmount(){
console.log("beforeunmount");
},
// 6.2dom元素被卸载完成
unmounted(){
console.log("unmounted");
}
}
script>
(2)创建一个名为Home的 Vue 组件,包含 beforeUnmount和unmounted 两个生命周期函数。代码如下:
<template>
<h2>homeh2>
template>
<script>
export default {
beforeUnmount() {
console.log("home的beforeunmount");
},
unmounted() {
console.log("home unmounted");
}
}
script>
我们可以看到,在这个演示中,页面中有计数器且组件 Home可以通过一个切换按钮显示和隐藏。
运行这个代码,并打开浏览器控制台,我们可以看到下面的输出:
点击按钮+1修改计数器数字后,控制台新增输出:
点击按钮隐藏home组件,控制台新增输出:
从上面的演示中,可以清晰的感受到各个生命周期函数是什么时候执行的;其中非常重要的 created、mounted 和 unmounted
三个生命周期函数应用场景:
某些情况下,我们在组件中想要直接获取到元素对象或者子组件实例:
不推荐进行原生DOM操作
的;给元素或者组件绑定一个ref的attribute属性
;组件实例有一个$refs属性:
它一个对象Object,持有注册过ref attribute 的所有DOM元素和组件实例
。
当我们需要在 Vue 组件中操作 DOM 元素时,可以使用 ref(s) 这个特殊的属性来访问元素:
- ref 属性可以用在普通的 HTML 元素上,也可以用在子组件上;
- 通过 ref(s),我们可以获取到元素的真实 DOM 节点或者组件实例,从而进行一些操作,比如访问元素的属性、绑定事件、修改样式等等
具体来说, ref(s) 包含两种方式,字符串形式和函数形式:
(1)使用字符串:我们可以在元素上通过 v-model 或其他属性为元素指定一个名称,接着在组件的 $refs 对象中使用该名称访问元素,例如:
<template>
<div>
<button ref="myBtn" @click="clickHandler">Click me!button>
div>
template>
<script>
export default {
methods: {
clickHandler () {
console.log(this.$refs.myBtn.value)
}
}
}
script>
上面的例子中,我们在按钮上使用 ref 属性并将其命名为 myBtn
。在该组件的 methods 中,我们可以通过 this.$refs.myBtn 访问到该按钮
,从而获得 value 属性并打印到控制台上。
(2)使用函数:除了字符串形式,我们还可以通过一个函数返回值来动态地给 ref 赋值。这种方式可以用来在组件中引用其它组件的实例。例如:
<template>
<div>
<custom-widget ref="myWidget">custom-widget>
div>
template>
<script>
import CustomWidget from './CustomWidget.vue'
export default {
components: {
CustomWidget
},
mounted () {
const widgetInstance = this.$refs.myWidget;
widgetInstance.doSomething();
// this.$refs.myWidget.doSomething();
}
}
script>
在上面的代码中,我们使用 CustomWidget 组件添加 ref 属性。当这个组件渲染完成后,我们可以通过 $refs.myWidget 获取组件的实例并调用 doSomething 方法。
总结:
(1)需要注意的是,使用 $refs 可能需要在组件已经被挂载后才能正常访问到。
(2)另外,$refs 是一个非响应式的属性
,也就是说,如果使用 $refs 来访问某个组件实例或 DOM 元素,当它发生变化时是无法触发响应式更新的,这时候,就需要使用其他的数据传递方法。