微信小程序生命周期学习笔记-组件
生命周期包含应用生命周期、页面生命周期和组件生命周期。现在我们来学习组件的生命周期。
学习这一章节之前,需要先学习以下内容:
1.小程序的组件、自定义组件
2.页面节点树
3.应用生命周期、页面生命周期(重点是探索的方法)
微信开放文档:组件的生命周期,指的是组件自身的一些函数,这些函数在特殊的时间点或遇到一些特殊的框架事件时被自动触发。
和应用(小程序)和页面一样,小程序的组件也同样拥有生命周期。如果你能够理解上文所介绍的页面生命周期,那么组件生命周期对你而言便不成问题。
现在我们来介绍两种与组件有关的生命周期:一种是组件自身的生命周期,一种是组件所在页面的生命周期。
我们先来新建一个自定义组件,然后打开这个组件的js文件。不同于我们在学习应用生命周期和页面生命周期时所看到的全局js文件和页面的js文件,新建组件时的js文件中没有对组件生命周期函数进行定义。我们需要自己来写生命周期函数并进行相应的测试。
组件自身的生命周期
我们先来看看组件自身有哪些生命周期函数:
生命周期 | 参数 | 描述 |
---|---|---|
created | 无 | 在组件实例刚刚被创建时执行 |
attached | 无 | 在组件实例进入页面节点树时执行 |
ready | 无 | 在组件在视图层布局完成后执行 |
moved | 无 | 在组件实例被移动到节点树另一个位置时执行 |
detached | 无 | 在组件实例被从页面节点树移除时执行 |
error | Object Error | 每当组件方法抛出错误时执行 |
其中moved涉及到组件间关系的相关内容,难度较高,与前两个生命周期的关联程度也较少,这里暂时不做详细介绍。
在介绍各个生命周期函数之前,我们先要对生命周期函数的定义做一点说明:
在新建的js文件当中,我们能够看到开发者工具为我们创建好的框架如下:
根据微信开放文档给我们的建议,我们最好不要把组件自身的这些生命周期函数直接在与properties、data、methods同层级下声明,而是在这一层级下的lifetimes里声明,例如:
properties: {
},
lifetimes: {
//在这里定义组件自身的生命周期函数
},
created
组件何时被小程序创造出来?当组件所在页面被调出来时,由于组件在页面wxml中被调用,此时组件必须被创造出来,否则无法在这个页面当中使用。
和之前一样的测试方法,给出测试代码(放在lifetimes中):
lifetimes:{
created: function() {
console.log("created");
}
}
有了前面的学习和练习,那么这段代码在做什么样的事情我们就不必再说明了。当我们打开一个含有这个组件的页面时,我们就可以看到console中有“created”字符串输出。
那么它和页面的一些生命周期函数的调用顺序如何呢?
我们接下来把之前学习的页面周期函数中的输出全部加在页面的js文件中,来看一下效果:
也就是说,created的调用时间点在page.onLoad之前,即组件的创建在页面的加载(初始化)之前。
attached
根据我们刚刚看到的表格,attached函数是在组件实例进入页面节点树时执行。组件实例需要先被创建,然后才能进入页面节点树(有关页面节点树相关问题在这里不作详细说明)。所以我们可以得出,attached函数是在created函数之后执行。
用代码测试一下:
lifetimes:{
attached: function() {
console.log("attached");
}
}
事实与我们的推断相符。
那么attached和页面生命周期执行的先后顺序如何?大家可以自行尝试。
结果是attached执行时间点晚于created,早于page.onLoad。说明页面加载的过程中包含组件实例进入页面节点树,也就是说组件是页面的必要成分(如果这个页面有组件的话),组件不先安置好,是没有办法完整加载页面的。
ready
ready函数是在组件在视图层布局完成后执行。你可能会有些迷惑,视图层布局完成是什么意思?是在手机页面渲染的过程?还是在构建页面视图、也就是在页面加载的过程中完成的?解决问题的办法,还是测试。
代码如下:
lifetimes:{
ready: function() {
console.log("ready");
}
}
具体是在什么时候,大家可以同样把用页面生命周期的输出做比对,你会发现:
(这里面有两个ready,其中ready是组件生命周期ready函数中输出的,Ready是页面生命周期onReady函数输出的)
在学习页面生命周期时,我们就学习过,onLoad是在页面加载结束后执行,而这个时间点也是onShow的执行时间点,只是前者先于后者执行。这里面我们会发现,ready是晚于Show的,说明这个组件渲染结束是在页面加载结束后,在手机端进行页面渲染时,页面中的组件渲染结束后执行的。页面基本都不止含有组件,所以页面渲染完成的时间点一般情况下都会在组件渲染结束之后。
detached
detached这个词和attached长得很像,我们也知道,英文单词中的前缀de-有时表示反义。那么说明detached和attached是反义词。
attached是在组件实例进入页面节点树时执行,那显而易见,detached就是在组件实例被从页面节点树移除时执行。怎么移除?一个有组件的页面被卸载的过程中,必然要经过组件被移除的过程。
我们先来测试一下detached函数执行的时间点。
lifetimes:{
detached: function() {
console.log("detached");
}
}
在测试前我们可以回想一下,当一个页面被卸载时,页面生命周期函数onUnload会被执行。那么究竟是onUnload函数先执行,还是detached函数先执行?在测试之前,我们可以先猜一猜最后结果是什么。
接下来要公布结果了:
和你猜的结果是否一样呢?
对于这个结果,我们有一个简单的理解方法:我们在学习onUnload时,学到他是监听页面卸载时执行的。那它是卸载之前执行还是卸载之后执行呢?我们可以这样去想,如果页面被卸载后再执行,而页面已经被卸载了,理论上这个页面不会再跑代码了。那么这个onUnload该如何执行?或者从它的作用出发思考,onUnload是我们在页面被卸载时实现一些我们想做的功能,说明这个功能只能在这个即将被卸载的页面上执行。页面被卸载了,那又该如何执行呢?
所以我们也就可以理解为什么onUnload是在卸载之前执行了。既然如此,我们又知道,卸载组件一定是在卸载页面的过程当中,也就是说,在卸载过程之前执行的onUnload一定会早于在卸载页面过程当中、在卸载组件之前(思考方式和onUnload一样)执行的detached。
error
error可是一个熟面孔了。我们在应用生命周期就学过onError,其实组件自身生命周期的error和onError没什么两样,同样要传递一个参数,这个参数是一个Object,用来记录错误信息的。
那么就给出测试代码,大家用学习onError时我们使用的方法,试一试这个error函数吧!打印一个字符串“error”,并输出错误信息。
代码如下:
lifetimes:{
error: function(err) {
console.log("error");
console.log(err);
}
}
如何引发错误呢?大家在编写组件时可以试着做一个事件绑定,在js中写函数时加入一行错误代码即可。这样在触发绑定的事件时就会弹错,console就会输出“error”和字符串,以及和红框中完全相同的错误信息(一样的错误信息会看到两个,一个是红底的,是工具自带的,一个是我们代码里输出的)。
理论上“error”字符串和我们输出的灰底的错误信息是挨在一起的,并且在红底的错误信息的上方。(其实这也说明工具提供错误信息的时间点在组件生命周期之后)。
组件所在页面的生命周期
微信开放文档:还有一些特殊的生命周期,它们并非与组件有很强的关联,但有时组件需要获知,以便组件内部处理。这样的生命周期称为“组件所在页面的生命周期”。
可用的组件所在页面的生命周期有以下三种:
生命周期 | 参数 | 描述 |
---|---|---|
show | 无 | 组件所在的页面被展示时执行 |
hide | 无 | 组件所在的页面被隐藏时执行 |
resize | 无 | 组件所在的页面尺寸变化时执行 |
学习过页面生命周期,这些函数对我们来说都很好理解。
在学习之前我们要说明这三个组件所在页面的生命周期的声明位置。和组件自身的生命周期相似,在小程序中不建议将这些生命周期直接命名在Components之中,也就是不建议与上文的lifetimes同层级。我们的定义方法是该层级中的pageLifetimes(L是大写!)里面声明。
有了页面生命周期和组件自身的生命周期的学习,这些函数的测试方法相信大家已经能够掌握。我们这里就不再过多叙述,只将测试代码一起给出,希望大家自己尝试测试。
其中resize函数的测试较为特殊,需要启用屏幕旋转支持。本节不对此进行详细描述,详见微信开放文档:响应显示区域变化
https://developers.weixin.qq.com/miniprogram/dev/framework/view/resizable.html#在手机上启用屏幕旋转支持
pageLifetimes: {
show: function() {
console.log("page-show");
},
hide: function() {
console.log("page-hide");
},
resize: function() {
console.log("page-resize")
}
}
小结
到这里小程序的三种生命周期就全部介绍完了。这三种生命周期的理解,对自己想实现的许多功能都有很大的帮助。假如我们在之前提到的:在将小程序切入后台时,一些计时器不应该继续计时;如何判断使用小程序的人是否分享了这个小程序;使用的这个组件与页面相关,当这个页面被打开时,组件有这样的功能,关闭时又有那样的效果……通过学习,这些情况的实现方法,相信大家心中已经有答案了。
我们在学习过程中,也提到了输出探索的方法,这也是学习这方面内容的一个比较重要的学习方法。其实通过生命周期的学习,我们也在着重培养一个学习方式,有一部分的测试是让读者自己来完成的。如果这些任务读者都可以自己完成,并得出结论,那么这一部分的内容便是真正掌握了。
事实上这三种生命周期有很多地方都是共通的,学会了应用生命周期,我们就可以举一反三,在学习之前就可以想象出页面和组件的生命周期是什么样子的,是什么样的原理。在学习微信小程序、乃至整个信息技术的各个领域都是一样,我们在学习新知识时,或许都能找到一些我们之前学到过的知识的影子,与那些知识联系起来,构建新知识的架构,对这些新知识的理解会更进一步。
希望对生命周期的这些介绍与讲解对大家有帮助!
新书介绍
以下是本人3月份出版的新书,拜托多多关注!
本书利用Python 的标准GUI 工具包tkinter,通过可执行的示例对23 个设计模式逐个进行说明。这样一方面可以使读者了解真实的软件开发工作中每个设计模式的运用场景和想要解决的问题;另一方面通过对这些问题的解决过程进行说明,让读者明白在编写代码时如何判断使用设计模式的利弊,并合理运用设计模式。
对设计模式感兴趣而且希望随学随用的读者通过本书可以快速跨越从理解到运用的门槛;希望学习Python GUI 编程的读者可以将本书中的示例作为设计和开发的参考;使用Python 语言进行图像分析、数据处理工作的读者可以直接以本书中的示例为基础,迅速构建自己的系统架构。
觉得本文有帮助?请分享给更多人。
关注微信公众号【面向对象思考】轻松学习每一天!
面向对象开发,面向对象思考!