生命周期与钩子函数
生命周期
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("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){ 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> <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> <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>
<h1>vue数据变视图没有变--{{obj.name}}--{{obj.age}}</h1> <button @click="fun()">点我修改数据</button> </div> </template> <script> export default { methods:{ fun(){ 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("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>
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" } } } }
|