onmounted vue3_Vue3.x 生命周期 和 Composition API 核心语法理解
1 Vue2.x 生命周期回顾
beforeCreate
,在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。created
,在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前尚不可用。beforeMount
,在挂载开始之前被调用:相关的 render 函数首次被调用。mounted
,实例被挂载后调用,这时el
被新创建的vm.$el
替换了。如果根实例挂载到了一个文档内的元素上,当mounted被调用时vm.$el
也在文档内。beforeUpdate
,数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。updated
,由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。activated
,被 keep-alive 缓存的组件激活时调用。deactivated
,被 keep-alive 缓存的组件停用时调用。beforeDestroy
,实例销毁之前调用。在这一步,实例仍然完全可用。destroyed
,实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。errorCaptured
,当捕获一个来自子孙组件的错误时被调用。
参考:https://cn.vuejs.org/v2/api/#选项-生命周期钩子
以下是整个生命周期图示:
参考:https://cn.vuejs.org/v2/guide/instance.html#生命周期图示
2 Vue3.x 生命周期变化
被替换
beforeCreate -> setup()
created -> setup()
重命名
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeDestroy -> onBeforeUnmount
destroyed -> onUnmounted
errorCaptured -> onErrorCaptured
新增的
新增的以下2个方便调试 debug
的回调钩子:
onRenderTracked
onRenderTriggered
参考:https://vue-composition-api-rfc.netlify.com/api.html#lifecycle-hooks
特别说明
由于 Vue3.x 是兼容 Vue2.x 的语法的,因此为了保证 Vue2.x 的语法能正常在 Vue3.x 中运行,大部分 Vue2.x 的回调函数还是得到了保留。比如:虽然 beforeCreate
、 created
被 setup()
函数替代了,也就是说在 Vue3.x 中建议使用 setup()
,而不是旧的API,但是如果你要用,代码也是正常执行的。
但是,以下2个生命周期钩子函数被改名后,在 Vue3.x 中将不会再有 beforeDestroy
和 destroyed
。
beforeDestroy -> onBeforeUnmount
destroyed -> onUnmounted
另外,假如 Vue3.x 在 Q2 如期 Release 的话,大家一定要注意,在混合使用 Vue2.x 和 Vue3.x 语法的时候,特别要注意这2套API的回调函数的执行顺序。
3 Vue2.x + Composition API 对比 Vue3.x 生命周期执行顺序
当 Vue3.x 正式 Realease 以后,我可能会先使用 Vue2.x + Composition API
,完了再使用 Vue3.x
搭建新的基础框架。
那我今天主要关心的一个问题,一旦我使用 Vue2.x + Composition API
进入过渡期后,当我再使用 Vue3.x
搭建新的框架,那么之前的基础组件还能使用么?
先测试下生命周期函数的执行顺序。
3.1 Vue2.x + Composition API 生命周期执行顺序
如下示例,在 Vue2.x 中引入兼容包 Composition API,然后Vue2.x 和 Vue3.x 的生命周期函数混合使用。
{{ id }} {{ name }}
import {
ref,
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted
} from '@vue/composition-api';
export default {
setup() {
const id = ref(1)
console.log('setup')
onBeforeMount(() => {
console.log('onBeforeMount')
})
onMounted(() => {
console.log('onMounted')
})
onBeforeUpdate(() => {
console.log('onBeforeUpdate')
})
onUpdated(() => {
console.log('onUpdated')
})
onBeforeUnmount(() => {
console.log('onBeforeUnmount')
})
onUnmounted(() => {
console.log('onUnmounted')
})
// 测试 update 相关钩子
setTimeout(() => {
id.value = 2
}, 2000)
return {
id
}
},
data() {
console.log('data')
return {
name: 'lilei'
}
},
beforeCreate() {
console.log('beforeCreate')
},
created() {
console.log('created')
},
beforeMount() {
console.log('beforeMount')
},
mounted() {
console.log('mounted')
setTimeout(() => {
this.id = 3;
}, 4000)
},
beforeUpdate() {
console.log('beforeUpdate')
},
updated() {
console.log('updated')
},
beforeUnmount() {
},
unmounted() {
console.log('unmounted')
},
beforeDestroy() {
console.log('beforeDestroy')
},
destroyed() {
console.log('destroyed')
}
}
执行结果:
1. beforeCreate2. setup3. data4. created5. beforeMount6. onBeforeMount7. mounted8. onMounted9. beforeUpdate10. onBeforeUpdate11. updated12. onUpdated13. beforeDestroy14. onBeforeUnmount15. destroyed16. onUnmounted
结论
在 Vue2.x
中通过补丁形式引入 Composition API
,进行 Vue2.x
和 Vue3.x
的回调函数混用时:Vue2.x 的回调函数会相对先执行,比如:mounted
优先于 onMounted
。
3.2 Vue3.x 生命周期执行顺序
以下直接使用 Vue3.x 语法,看看其在兼容 Vue2.x 情况下,生命周期回调函数混合使用的执行顺序。
{{ id }} {{ name }}
import {
ref,
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted,
onRenderTracked,
onRenderTriggered
} from 'vue';
export default {
setup() {
const id = ref(1)
console.log('setup')
onBeforeMount(() => {
console.log('onBeforeMount')
})
onMounted(() => {
console.log('onMounted')
})
onBeforeUpdate(() => {
console.log('onBeforeUpdate')
})
onUpdated(() => {
console.log('onUpdated')
})
onBeforeUnmount(() => {
console.log('onBeforeUnmount')
})
onUnmounted(() => {
console.log('onUnmounted')
})
onRenderTracked(() => {
console.log('onRenderTracked')
})
onRenderTriggered(() => {
console.log('onRenderTriggered')
})
// 测试 update 相关钩子
setTimeout(() => {
id.value = 2;
}, 2000)
return {
id
}
},
data() {
console.log('data')
return {
name: 'lilei'
}
},
beforeCreate() {
console.log('beforeCreate')
},
created() {
console.log('created')
},
beforeMount() {
console.log('beforeMount')
},
mounted() {
console.log('mounted')
setTimeout(() => {
this.id = 3;
}, 4000)
},
beforeUpdate() {
console.log('beforeUpdate')
},
updated() {
console.log('updated')
},
beforeUnmount() {
console.log('beforeUnmount')
},
unmounted() {
console.log('unmounted')
}
}
>
执行结果:
1. beforeCreate2. data3. created4. onRenderTracked5. onRenderTracked6. onBeforeMount7. beforeMount8. onMounted9. mounted10. onRenderTriggered11. onRenderTracked12. onRenderTracked13. onBeforeUpdate14. beforeUpdate15. onUpdated16. updated17. onBeforeUnmount18. beforeUnmount19. onUnmounted20. unmounted
结论
在 Vue3.x
中,为了兼容 Vue2.x
的语法,所有旧的生命周期函数得到保留(除了 beforeDestroy
和 destroyed
),当生命周期混合使用时:Vue3.x 的生命周期相对优先于 Vue2.x 的执行,比如:onMounted
比 mounted
先执行。
4 Vue2.x + Composition API 过度到 Vue3.x 生命周期总结
综上所述:
在
Vue2.x
中通过补丁形式引入Composition API
,进行Vue2.x
和Vue3.x
的回调函数混用时:Vue2.x 的回调函数会相对先执行,比如:mounted
优先于onMounted
。在
Vue3.x
中,为了兼容Vue2.x
的语法,所有旧的生命周期函数得到保留(除了beforeDestroy
和destroyed
)。当生命周期混合使用时:Vue3.x 的生命周期相对优先于 Vue2.x 的执行,比如:onMounted
比mounted
先执行。
通过对比可以得出:当你的主版本是哪个,当生命周期混用时,谁的回调钩子就会相对优先执行。
所以,这里就会有点坑!为了给减小以后不必要的麻烦,如果大家在 Vue2.x
中通过补丁形式引入 Composition API
的使用的时候,建议:
不要混用Vue2.x和Vue3.x的生命周期。要么你继续使用 Vue2.x 的钩子函数,要么使用 Vue3.x 的钩子函数,这样就没问题。
在原则1的情况下,建议源码从工程或者目录就区分开新老版本。方便以后升级或者被引入到 Vue3.x 使用的时候,更有针对性兼容测试。
5 Composition API 核心语法
以下内容,大部分参考官方:Vue Composition API(https://vue-composition-api-rfc.netlify.com/api.html)
5.1 setup 主执行函数
setup
是 Composition API 的核心,可以说也是整个 Vue3.x 的核心。
setup
就是将 Vue2.x 中的beforeCreate
和created
代替了,以一个setup
函数的形式,可以灵活组织代码了。setup
还可以 return 数据或者 template,相当于把data
和render
也一并代替了!
为什么说 setup
灵活了呢?因为在这个函数中,每个生命周期可以是一个函数,在里面执行,以函数的方式编程。
下面看看其几个核心特点:
1 返回一组数据给template
{{ count }} {{ object.foo }}
import { ref, reactive } from 'vue'
export default {
setup() {
const count = ref(0)
const object = reactive({ foo: 'bar' })
// expose to template
return {
count,
object
}
}
}
2 使用jsx语法
import { h, ref, reactive } from 'vue'export default { setup() {const count = ref(0)const object = reactive({ foo: 'bar' })
return () => h('div', [ h('p', { style: 'color: red' }, count.value), h('p', object.foo) ]) }}
3 Typescript Type
interface Data { [key: string]: unknown}
interface SetupContext { attrs: Data slots: Slots emit: ((event: string, ...args: unknown[]) => void)}
function setup( props: Data, context: SetupContext): Data
4 参数
需要注意的是,在 setup
函数中,取消了 this
!两方面的原因:
由于
setup
是一个入口函数,本质是面向函数编程了,而this
是面向对象的一种体现!在完全基于函数的编程世界中,这个this
就很难在能达到跟 Vue2.x 那种基于 OOP 思想的 Options 机制的实现的效果。同样是基于函数式编程,那么如果加上 this,对于新手而言,本来 this 就不好理解,这时候就更加懵逼了。比如:
setup() {function onClick() {this // 如果有 this,那么这里的 this 可能并不是你期待的! }}
取消了 this
,取而代之的是 setup
增加了2个参数:
props,组件参数
context,上下文信息
setup(props, context) {// props// context.attrs// context.slots// context.emit}
也许你会有疑问,仅有这2个参数就够了么?够了。你在 Vue2.x 的时候,this
无法就是获取一些 data、props、computed、methods 等么?
其实,这2个参数都是外部引入的,这个没办法只能带入初始化函数中。除此之外,你组件上用到的所有 this 能获取的数据,现在都相当于在 setup 中去定义了,相当于局部变量一样,你还要 this 干嘛呢?
比如:
setup(props, context) {// dataconst count = ref(1)
// 生命周期钩子函数 onMounted(() => {console.log('mounted!') })
// 计算函数const plusOne = computed(() => count.value + 1)
// methods 方法const testMethod = () => {console.log('methods'); }
// return to templatereturn { count, testMethod }}
一切在 setup
中,都相当于变成了 局部变量
了,你还要 this
干嘛?
当然,如果你要讲 Vue2.x 和 Vue3.x 混用!那就很别扭了,以后用 this,以后又不能用,你自己也会懵逼,所以在此建议:虽然Vue3.x兼容Vue2.x语法,但是不建议混合使用各自语法!
5.2 reactive 方法
被 reactive
方法包裹后的 对象
就变成了一个代理对象,相当于 Vue2.x 中的 Vue.observable()
。也就可以实现页面和数据之间的双向绑定了。
这个包裹的方法是 deep
的,对所有嵌套的属性都生效。
注意: 一般约定 reactive
的参数是一个对象,而下文提到的 ref
的参数是一个基本元素。但如果反过来也是可以的,reactive
其实可以是任意值,比如:reactive(123)
也是可以变成一个代理元素,可以实现双向绑定。
比如:
{{ obj1.cnt }}{{ obj2.cnt }}
import { reactive } from 'vue'
setup() {
// 普通对象
const obj1 = {
cnt: 1
}
// 代理对象
const obj2 = reactive({
cnt: 1
})
obj1.cnt++
obj2.cnt++
return {
obj1,
obj2
}
}
页面显示结果:
12
可以看到,普通对象属性更新时,页面是不会同步更新的。只有代理对象,才可以实现双向绑定。
5.3 ref 方法
被 ref
方法包裹后的 元素
就变成了一个代理对象。一般而言,这里的元素参数指 基本元素
或者称之为 inner value
,如:number, string, boolean,null,undefied 等,object 一般不使用 ref
,而是使用上文的 reactive
。
也就是说 ref
一般适用于某个元素的;而 reactive
适用于一个对象。
ref
也就相当于把单个元素转换成一个 reactive
对象了,对象默认的键值名是:value
。
比如:
setup() {const count = ref(100)}
被 ref
包裹后的元素变成一个代理对象,效果就相当于:
setup() {const count = reactive({ value: 100 })}
因为变成了一个代理对象,所以取值的时候需要 .value
:
setup() {const count = ref(100)console.log(count.value) // output: 100}
另外 ref
的结果在 template
上使用时,会自动打开 unwrap
,不需要再加 .value
{{ count }}
export default {
setup() {
return {
count: ref(0)
}
}
}
以下是一些基本元素 ref
的结果:
setup() {console.log(ref(100).value) // output: 100console.log(ref('test').value) // output: testconsole.log(ref(true).value) // output: trueconsole.log(ref(null).value) // output: nullconsole.log(ref(undefined).value) // output: undefinedconsole.log(ref({}).value) // output: {}}
5.3 isRef 方法
判断一个对象是否 ref
代理对象。
const unwrapped = isRef(foo) ? foo.value : foo
5.4 toRefs 方法
将一个 reactive
代理对象打平,转换为 ref
代理对象,使得对象的属性可以直接在 template
上使用。
看看下面的例子你可能就明白它的作用了。
{{ obj.count }}{{ count }}{{ value }}
export default { setup() {const obj = reactive({ count: 0, value: 100 })return { obj,// 如果这里的 obj 来自另一个文件,// 这里就可以不用包裹一层 key,可以将 obj 的元素直接平铺到这里// template 中可以直接获取属性 ...toRefs(obj) } }}
5.5 computed 函数
与 Vue2.x 中的作用类似,获取一个计算结果。当然功能有所增强,不仅支持取值 get
(默认),还支持赋值 set
。
注意: 结果是一个 ref
代理对象,js中取值需要 .value
。
正常获取一个计算结果:
const count = ref(1)const plusOne = computed(() => count.value + 1)
console.log(plusOne.value) // 2
plusOne.value++ // 报错,因为未实现 set 函数,无法赋值操作!
当 computed 参数使用 object 对象书写时,使用 get 和 set 属性。set 属性可以将这个对象编程一个可写的对象。
也就是说 computed
不仅可以获取一个计算结果,它还可以反过来处理 ref
或者 reactive
对象!
const count = ref(1)const plusOne = computed({ get: () => count.value + 100, set: val => { count.value = val - 1 }})
plusOne.value = 1console.log(count.value) // 0console.log(plusOne.value) // 100
plusOne.value = 1
相当于给计算对象赋值,会触发 set
函数,于是 count
值被修改了。
5.5 readonly 函数
使用 readonly
函数,可以把 普通 object 对象
、reactive 对象
、ref 对象
返回一个只读对象。
返回的 readonly 对象,一旦修改就会在 console 有 warning 警告。程序还是会照常运行,不会报错。
const original = reactive({ count: 0 })
const copy = readonly(original)
watchEffect(() => {// 只要有数据变化,这个函数都会执行console.log(copy.count)})
// 这里会触发 watchEffectoriginal.count++
// 这里不会触发上方的 watchEffect,因为是 readonly。copy.count++ // warning!
还有一些 API 诸如 watch
、watchEffect
等,这里就不说了,以上是一些比较重要的的语法,希望能对大家有所帮助。
转发在看就是最大的支持❤️
onmounted vue3_Vue3.x 生命周期 和 Composition API 核心语法理解相关推荐
- 关于Vue3组合式API(Composition API)的个人理解
首先,关于组合式API现已有众多大佬发布了相关介绍及相关教程,但是个人在学习过程中还是花了比较多的时间去理解 " 组合式API " 这个概念. 因为目前搜索引擎排的比较前面的文章其 ...
- Vue2.0 探索之路——生命周期和钩子函数的一些理解
前言 在使用vue一个多礼拜后,感觉现在还停留在初级阶段,虽然知道怎么和后端做数据交互,但是对于mounted这个挂载还不是很清楚的.放大之,对vue的生命周期不甚了解.只知道简单的使用,而不知道为什 ...
- vue 声明周期函数_Vue2.0 探索之路——生命周期和钩子函数的一些理解
前言 在使用vue一个多礼拜后,感觉现在还停留在初级阶段,虽然知道怎么和后端做数据交互,但是对于mounted这个挂载还不是很清楚的.放大之,对vue的生命周期不甚了解.只知道简单的使用,而不知道为什 ...
- Vue生命周期和钩子函数的一些理解
vue生命周期简介 咱们从上图可以很明显的看出现在vue2.0都包括了哪些生命周期的函数了. 生命周期探究 对于执行顺序和什么时候执行,看上面两个图基本有个了解了.下面我们将结合代码去看看钩子函数的执 ...
- mounted钩子函数_Vue 探索之路——生命周期和钩子函数的一些理解
对于执行顺序和什么时候,下面我们将结合代码去看看钩子函数的执 行 <!DOCTYPE html> <html> <head><title></ti ...
- 数据API开发如何快速上手:先了解什么是数据API生命周期管理
任何事务都有一个生命周期,数据API也不例外.上一段视频,我们解释了什么是数据API?.这段视频,我们来了解一下数据API的生命周期管理. 我们把每个数据API生命周期,划分为API规划.API开发. ...
- 一幅长文细学Vue(十三)——组合式中的生命周期
13 组合式API(四) 摘要:每个 Vue 组件实例在创建时都需要经历一系列的初始化步骤,比如设置好数据侦听,编译模板,挂载实例到 DOM,以及在数据改变时更新 DOM.在此过程中,它也会运行被称为 ...
- 线程的生命周期其实没有我们想象的那么简单!!
来自:冰河技术 写在前面 在[高并发专题]中的<高并发之--线程与多线程>一文中,我们简单介绍了线程的生命周期和线程的几个重要状态,并以代码的形式实现了线程是如何进入各个状态的.今天,我们 ...
- 页面生命周期_微信小程序的生命周期学习笔记-应用篇
在我们学习微信小程序的过程当中,我们会参考很多资料.在这些资料中,我们经常能够看到"生命周期"四个字,在前面的课程中也提到过.在这里做一个说明. 生命周期是一类函数的统称,这些函数 ...
最新文章
- 第五次毕业设计任务书
- 【Qt】仿360安全卫士界面(自定义阴影边框类)
- formdata接收数据怎么接收数组_LBT是什么?怎么增加通信可靠性?
- .NET Core计划弃用project.json
- 一个德国设计奖,怎么就成了中国品牌的财富密码
- linux未被识别crond服务,linux 定时任务 crond 服务介绍
- 蚂蚁金服安全应急响应中心上线
- 猫盘群晖外部网络访问的三种方法:公网IP、内网穿透、qc的实际评测
- android的otg功能,Android实现OTG功能
- Unity XLua学习笔记(四):Hotfix热补丁
- 950个织梦网dede模板源码
- ble学习笔记九----------ble协议栈之OSAL的运行机理
- 【产品志】显示器的选购
- 重置计算机网络配置后上不了网,路由器重置后上不了网怎么办 怎么重新设置路由器...
- ORB-SLAM3 IMU(李群)+Frame+KeyFrame+MapPoint
- Java+JSP基于ssm广州市家教中介服务网站-计算机毕业设计
- visualfreebasic 5正式版
- 利用放大器调整输出信号的共模电压——放大器电路设计思路(图文)
- 王道数据结构课代表 - 考研数据结构 第四章 串-KMP(看毛片算法) 究极精华总结笔记(C版本)
- 营销新策略——幸运抽奖
热门文章
- 在GNS3中使用SecureCRT6.1出错的解决方案
- 如何学习数据可视化技术
- 大数据可视化分析方法与流程
- Linux终端设置成256色模式,如何设置LinuxX终端,使Emacs可以访问256色?
- arrayvalue php,phparrayvalue
- shell定时执行java,shell学习之定时运行作业
- cef linux 多线程模式,CEF3开发者系列之进程和线程
- android反编译工具mercury_JAVA反编译工具集锦
- java第七章第九题_Java2程序设计基础第七章课后习题
- lvm讲解与磁盘挂载问题排除