生命周期与钩子函数

生命周期

vue实例从创建到销毁的过程 会有很多个阶段 每个阶段都会自动执行一些函数(生命周期的钩子函数)

钩子函数

在程序运行的特定阶段内被自动调用的函数

生命周期的钩子函数

有4组 8个 可以帮助我们开发者 在项目的某些特定阶段自动执行一些逻辑(页面加载完自动发送数据请求)

实例创建

实例创建之前—beforeCreate

实例创建之后—created

模板渲染

模板渲染之前—beforeMount

模板渲染之后—mounted

数据更新

数据更新之前—beforeUpdate

数据更新之后—updated

实例销毁

实例销毁之前—beforeDestory

实例销毁之后—destoryed

vue初次加载执行那些生命周期的钩子函数?

执行实例创建前后 (要说英文) 模板渲染前后(要说英文)

什么是生命周期的钩子函数?

vue实例从创建到销毁的过程 会有很多个阶段 每个阶段都会自动执行一些函数 那么这些自动执行的函数 就是生命周期的钩子函数

生命周期几个阶段?

4个阶段 8个钩子 (最好把着8个钩子挨个说一遍)

dom渲染在那个阶段内执行完毕?

mounted阶段 模板渲染之后

请您简述每个生命周期的钩子函数?

实例创建之前—beforeCreate 在数据观测与初始化 事件还没有执行

实例创建之后—created 完成了数据的观测 实例中的属性与方法也都进行了初始化完毕 但是这个时候el属性还没显示

模板渲染之前—beforeMount 此时还没有开始进行页面之间的挂载 模板还没有在页面进行显示

模板渲染之后—mounted el已经成功的在页面进行了挂载显示

数据更新之前—beforeUpdate 在数据更新之前进行调用 我们在这个阶段内如果操纵数据再次修改 不会造成页面重复修改

数据更新之后—updated 数据修改完毕 页面也进行了更新显示

实例销毁之前—beforeDestory vue实例在销毁之前执行 在这个阶段 vue的各项功能还能正常使用

实例销毁之后—destoryed 什么都没有了

过滤器

在不改变原始数据的情况下格式化展示数据

在vue2x之后 vue中就取消了内置过滤器 全部变成了自定义过滤器

自定义过滤器

自定义全局过滤器—filter

可以在任何组件中随意使用

main.js中来完成编写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

// 定义全局过滤器
// Vue.filter("过滤器的名字",(val 你要过滤的数据)=>{ return 你的逻辑})
Vue.filter("xiaoming",(val)=>{
if(val.length>6){
return val.substr(0,3)+"..."
}else{
return val
}
})


new Vue({
render: h => h(App),
}).$mount('#app')

自定义局部过滤器—filters

只能在当前定义过滤器的组件内部进行使用

语法:/

写在与 data methods watch等同级的位置

filters:{

​ 过滤器的名字(){

​ }

}

使用过滤器就是在你想使用的数据后面 加 | 过滤器的名字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<template>
<div>
<div class="item" v-for="(v, i) in arr" :key="i">
<h1>{{ v.title|xiaoming }}</h1>
</div>
</div>
</template>

<script>
export default {
// 局部自定义过滤器
filters: {
xiaoming(val){
// 我要对需要过滤的数据 大于6位 保留5位加...
// 小于6位正常展示
if(val.length>6){
return val.substr(0,5)+"..."
}else{
return val
}
}
},
data() {
return {
arr: [
{ title: "这个杀手不太冷" },
{ title: "这个杀手不太冷好冷" },
{ title: "这个杀手" },
{ title: "这个杀手好冷" },
{
title:
"这个杀手不太冷呵呵额呵呵呵呵呵呵呵呵呵呵额呵呵呵呵呵呵呵呵呵呵呵",
},
],
};
},
};
</script>

<style>
.item {
width: 200px;
border: 2px solid red;
}
</style>

注意 全局和局部过滤器重名执行谁?

就近原则 执行局部的

自定义指令

本质就是指令 只是默认情况下vue给我们提供的内置指令不够用的时候我们可以自己新建创建一个指令

语法:

directives:{ //写在与data methods等同级的位置

​ 自定义指令的名字:{

​ 自定义指令的钩子(el 你把自定义指令绑定在哪里形参就是谁){

​ 你的逻辑

​ }

​ },

自定义指令的名字:{

​ xxxxxx

​ }

}

自定义指令的钩子函数:

bind :指令绑定到元素身上的时候只执行一次,用来做一次性初始化操作

unbind: 解除指令和元素的关联的时候只执行一次

update: 被绑定元素所在的模板更新时调用,不论绑定值是否变化,通过比较更新前后的绑定值

componentUpdate: 指令所在节点以及子节点更新的时候

inserted: 被绑定了指令的元素在插入页面的时候调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
<div>
<h1>自定义指令</h1>
<!-- 自定义指令也是指令 指令就是vue中带有v-xxx的html特殊属性 -->
<h1 v-elcolor>修改我的颜色</h1>
</div>
</template>
<script>
export default {
// 自定义指令
directives:{
elcolor:{
inserted(el){
el.style.color="red"
}
}
}
}
</script>
<style>
</style>

扩展–$set

vue数据变了视图没有变的情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<template>
<div>
<!-- 当运行的时候会发现数据变了 视图的age并没有发生改变 -->
<h1>vue数据变视图没有变--{{obj.name}}--{{obj.age}}</h1>
<button @click="fun()">点我修改数据</button>
</div>
</template>
<script>
export default {
methods:{
fun(){
this.obj.age=18
console.log(this.obj.age)
}
},
data(){
return {
obj:{
name:"xixi"
}
}
}
}
</script>
<style>
</style>

原理

为什么数据变了视图没有变

官方定义:如果在实例创建之后添加新的属性到实例之上 他是不会触发视图更新的

当vue data里面声明了对象或者数组(数组中值是对象)如果我们想在其中插入新属性的时候 不会触发视图更新

因为在vue2X中数据改变视图也发生改变是因为双向绑定 双向绑定中很重要的一点就是数据劫持 使用 object.defineProperty这个方法 因为这个方法有个小BUG 就是这个只会监听初始化data中存在的数据

但是初始化完成之后添加的新属性就不会被监听到 没有监听到就没有数据劫持 没有数据劫持就没有双向绑定 从而数据变了视图当然不会变

如果想变呢???

$set

给data中的数据添加新的属性并且让视图发生更新

this.$set(“你要操作的数据”,”新增的key”,”新增的val”)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<template>
<div>
<!-- 当运行的时候会发现数据变了 视图的age并没有发生改变 -->
<h1>vue数据变视图没有变--{{obj.name}}--{{obj.age}}</h1>
<button @click="fun()">点我修改数据</button>
</div>
</template>
<script>
export default {
methods:{
fun(){
// this.obj.age=18

// 使用$set修改
this.$set(this.obj,"age",666)
console.log(this.obj.age)
}
},
data(){
return {
obj:{
name:"xixi"
}
}
}
}
</script>

<style>
</style>

mixin 混入

主要就是用来封装组件中那些重复使用的方法 变量 生命周期等内容

1.在src下新建一个mixins的文件夹用来容纳混入的封装内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 封装混入的内容
let demod={
methods:{
fun(){
console.warn("我是一个函数");
}
},
data(){
return {
tex:"我是混入的变量"
}
}
}

// 不要忘了暴露
export default demod

分类

全局混入—mixin

可以在任何组件中使用混入的内容

在main.js中来进行配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

// 定义全局过滤器
// Vue.filter("过滤器的名字",(val 你要过滤的数据)=>{ return 你的逻辑})
Vue.filter("xiaoming",(val)=>{
if(val.length>6){
return val.substr(0,3)+"..."
}else{
return val
}
})

// 全局混入
import demod from "@/mixins"

Vue.mixin(demod)

new Vue({
render: h => h(App),
}).$mount('#app')

局部混入—mixins

只能在当前引用的组件中使用混入封装的内容

语法:写在与data methods 等同级位置 使用 mixins:[你引用的第一个混入,你引用的第二个混入,…n]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<div>
<h1>混入</h1>
<button @click="fun()">点我--{{text}}</button>
</div>
</template>

<script>
// @ 写在路径上就代表的是 src文件夹路径 在任何路径中只要有@ 那么就直接指向src文件夹

// 只要路径找到文件夹没有写文件夹的话 程序会自动去路径下寻找index.js
// 1.引用混入文件
import demod from "@/mixins"
export default {
// 使用局部混入
mixins:[demod]

}
</script>

<style>

</style>

扩展

文件夹别名

1.在根路径下 新建vue.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
module.exports={
devServer: {
proxy: { //配置跨域
'/api': {
target: 'http://www.weather.com.cn/', //需要解决跨域的地址
pathRewrite: {
'^/api': ''
}
},
}
},

// 配置文件夹别名
configureWebpack:{
resolve:{
alias:{
// "你要设置的别名":这个别名对应的路径
"xiaoming":"@/components"
}
}
}

}

自动开启浏览器

在devServer中设置 open属性 来进行自动开启浏览器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
module.exports={
devServer: {

// 注意位置 自动开启浏览器
open:true,
// 注意位置 自动开启浏览器

proxy: { //配置跨域
'/api': {
target: 'http://www.weather.com.cn/', //需要解决跨域的地址
pathRewrite: {
'^/api': ''
}
},
}
},

// 配置文件夹别名
configureWebpack:{
resolve:{
alias:{
// "你要设置的别名":这个别名对应的路径
"xiaoming":"@/components"
}
}
}
}

修改端口 – port

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
module.exports={
devServer: {

// 注意位置 自动开启浏览器
open:true,
// 注意位置 自动开启浏览器

// 注意位置 修改端口
port:8888,
// 注意位置 修改端口

proxy: { //配置跨域
'/api': {
target: 'http://www.weather.com.cn/', //需要解决跨域的地址
pathRewrite: {
'^/api': ''
}
},
}
},

// 配置文件夹别名
configureWebpack:{
resolve:{
alias:{
// "你要设置的别名":这个别名对应的路径
"xiaoming":"@/components"
}
}
}
}