Vue实例从创建到销毁的过程,就是生命周期。也就是从开始创建、初始化数据、编译模板、挂载 Dom→渲染、更新→渲染、卸载等一系列过程
钩子函数
1.钩子函数是Vue框架中内置的一些函数,随着Vue的生命周期阶段,自动执行
2.在特点的时间,执行特定的操作
阶段 方法名 初始化 beforeCreate-------created 挂载 beforeMount------mounted 更新 beforeUpdate-----updated 销毁 beforeDestroy-----destroyed
vue生命周期--->初始化阶段
//- beforeCreate:生命周期函数被执行`此时不能访问data和menthods等中的东西`
//- created:生命周期钩子函数被执行,实例创建`此时能访问data和menthods等中的东西`
<template>
<div>
<h1>{{ msg }}</h1>
<button @click="btn">点我</button>
<button @click="chexi">销毁/定时器</button>
</div>
</template>
<script>
export default {
data() {
return {
msg: "你好,生命周期",
time: 0,
};
},
methods: {
btn() {
this.msg = "hello word!";
},
chexi() {
//销毁当前组件
this.$destroy();
},
},
//初始化阶段,不能获取data里的数据
beforeCreate() {
console.log(this.msg);
},
//可以获取data数据,发网络请求
created() {
console.log(this.msg);
//不能获取真实HTML标签
},
}
挂载阶段
// 挂载阶段
/*
- 虚拟DOM挂载成真实DOM之前:
- beforeMount :生命周期钩子函数被执行
- Create: 把虚拟DOM和渲染的数据一并挂到真实DOM上
- 挂载完毕,mounted:生命周期钩子函数被执行
*/
//DOM挂载前触发
beforeMount() {
console.log("beforeMount", "dom挂载前触发");
console.log(document.querySelector("h1"));
},
mounted() {
console.log("已经挂载完成了");
//可以拿到真实HTML标签
//一般在这个函数中可以操作DOM元素
//可以发起ajax请求,请求初始数据
console.log(document.querySelector("h1"));
//定时器
// this.time = setInterval(() => {
// console.log(123);
// });
},
更新阶段
当data里数据改变, 更新DOM之前,beforeUpdate – 生命周期钩子函数被执行`此时获取不到更新的真实dom`
updated – 生命周期钩子函数被执行
//更新阶段
//data中变量发生改变时执行的过程
beforeUpdate() {
//不能获取到DOM改变后的数据,可以获取DOM改变前的数据
console.log(document.querySelector("h1").innerHTML);
console.log("beforeUpdate,DOM数据改变其触发");
},
updated() {
console.log("updated,DOM数据改变后触发");
//可以获取到DOM改变后的数据
console.log(document.querySelector("h1").innerHTML);
},
销毁阶段
当$destroy()被调用:比如组件DOM被移除(例v-if)
beforeDestroy:生命周期钩子函数被执行
拆卸数据监视器、子组件和事件侦听器
实例销毁后, 最后触发一个钩子函数
destroyed: 生命周期钩子函数被执行
//销毁阶段,当$destroy方法被调用的时候触发
beforeDestroy() {
//可以用来清除定时器,或者全局的事件
//当销毁组件的时候,是不会销毁定时器的,需要手动销毁
console.log("beforeDestroy,实列销毁前触发");
//清除定时器
clearInterval(this.time);
},
destroyed() {
console.log("destroyed,实列销毁后触发");
},
$refs
refs`可以用于获取dom元素
<template>
<div>
<p>1. 获取原生DOM元素</p>
<h1 id="h" ref="myH">我是一个孤独可怜又能吃的h1</h1>
</div>
</template>
<script>
// 目标: 获取组件对象
// 1. 创建组件/引入组件/注册组件/使用组件
// 2. 组件起别名ref
// 3. 恰当时机, 获取组件对象
export default {
mounted(){
console.log(document.getElementById("h")); // h1
console.log(this.$refs.myH); // h1
}
}
//通过id获取ref都可以获取原生dom标签
</script>
<style>
</style>
$refs-获取组件对象
获取组件对象,调用组件里的方法
//子组件demo
<template>
<div>
<p>我是Demo组件</p>
</div>
</template>
<script>
export default {
methods: {
fn(){
console.log("demo组件内的方法被调用了");
}
}
}
</script>
父组件获取子组件的组件对象,调用方法
$nextTick使用
/*
点击count++, 马上通过"原生DOM"拿标签内容, 无法拿到新值
*/
<template>
<div>
<p>1. 获取原生DOM元素</p>
<h1 id="h" ref="myH">我是一个孤独可怜又能吃的h1</h1>
<p>2. 获取组件对象 - 可调用组件内一切</p>
<Demo ref="de"></Demo>
<p>3. vue更新DOM是异步的</p>
<p ref="myP">{{ count }}</p>
<button @click="btn">点击count+1, 马上提
</div>
</template>
<script>
// 目标: 获取组件对象
// 1. 创建组件/引入组件/注册组件/使用组件
// 2. 组件起别名ref
// 3. 恰当时机, 获取组件对象
import Demo from './Child/Demo'
export default {
components: {
Demo
},
data(){
return {
count: 0
},
mounted(){
console.log(document.getElementById("h")); // h1
console.log(this.$refs.myH); // h1
let demoObj = this.$refs.de;
demoObj.fn()
},
methods: {
btn(){
this.count++; // vue监测数据更新, 开启一个DOM更新队列(异步任务)
console.log(this.$refs.myP.innerHTML); // 0
// 原因: Vue更新DOM异步
// 解决: this.$nextTick()
// 过程: DOM更新完会挨个触发$nextTick里的函数体
this.$nextTick(() => {
console.log(this.$refs.myP.innerHTML); // 1
})
}
}
}
</script>
//ref定义值,通过$refs.值 来获取组件对象,就能继续调用组件内的变量
<template>
<div>
<input ref="myInp" type="text" placeholder="这是一个输入框" v-if="isShow">
<button v-else @click="btn">点击我进行搜索</button>
</div>
</template>
<script>
// 目标: 点按钮(消失) - 输入框出现并聚焦
// 1. 获取到输入框
// 2. 输入框调用事件方法focus()达到聚焦行为
export default {
data(){
return {
isShow: false
}
},
methods: {
async btn(){
this.isShow = true;
// this.$refs.myInp.focus()
// 原因: data变化更新DOM是异步的
// 输入框还没有挂载到真实DOM上
// 解决:
// this.$nextTick(() => {
// this.$refs.myInp.focus()
// })
// 扩展: await取代回调函数
// $nextTick()原地返回Promise对象
await this.$nextTick()
this.$refs.myInp.focus()
}
}
}
</script>
数据请求在created和mouted的区别
created是在组件实例一旦创建完成的时候立刻调用,这时候页面dom节点并未生成mounted是在页面dom节点渲染完毕之后就立刻执行的触发时机上created是比mounted要更早的两者相同点:都能拿到实例对象的属性和方法讨论这个问题本质就是触发的时机,放在mounted请求有可能导致页面闪动(页面dom结构已经生成),但如果在页面加载前完成则不会出现此情况建议:放在create生命周期当中
面试题
1.Vue的nextTick的原理是什么
1.为什么需要nextTick,vue是异步修改DOM的,并且不鼓励开发之直接接触DOM,但有什么业务需要必须对数据更改--刷新后的DOM做相应的处理,这时候就可以用Vue.nextTick(callback)这个api
2.理解原理前的准备,首先需要指定时间循环中宏任务和微任务这两个概念。常见的宏任务有:script , setTimeout , setInterval , setImmediate
常见的微任务有:process , nextTick(Nodejs) , promise.then()
MutationObserve([API] 用来监视 DOM 变动。DOM 的任何变动,比如节点的增减、属性的变动、文本内容的变动)
3.理解ntxtTick的原理正式vue通过异步列控制DOM更新和nextTick回调函数先后执行的方式
2.vue生命周期总共分几个阶段
Vue实例从创建过程到销毁过程,就是生命周期。也就是从开始创建,初始化数据,编译模板,挂载DOM-->渲染、更新-->渲染、卸载等一系列过程,称为Vue的生命周期
1.beforeCreadte:\在实例化初始化之后,数据观测(data observer)和event/watcher事件配置之前被调用
2.created:在实例创建完成后被立即调用。在这一步,实例已完成以下配置:数据观测(data observer),属性和方法的运算,watch/event事件回调。然而,挂载阶段还没开始
3.beforeMount:在挂载开始之前被调用,相关的render函数首次被调用
4.mounted:el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子。如果root实例挂载了一个文档内原生,当mounted被调用时,vm.$el也在文档内
5.beforeUpdate:数据更新时调用,发生在虚拟DOM打补丁之前。这里适合在更新之前访问现有的DOM。比如手动移除已添加的事件监听器。该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务端进行
6.updated:由于数据更改导致的虚拟DOM中学渲染和打补丁,在这之后就会调用这个钩子。
7.activated:keep-alive组件激活时调用。该钩子在服务器端渲染期间不被调用
8.deactivated:keep-alive组件停用时调用。该钩子在服务器端渲染期间不被调用。
9.beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。该钩子在服务器端渲染期间不被调用。
10.destroyed:Vue实例销毁后调用。调用后,Vue实例指示的所有东西都会解除绑定,所有的事件监听会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。
11.errorCaptured(2.5.0+新增):当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数,错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子开源返回false以阻止该错误继续向上传播
第一次加载页面会触发哪几个钩子函数
当页面第一次加载时会触发beforeCreate , created , beforeMount , mounted这几个钩子函数