首页前端开发JavaScript微信小程序组件生命周期的踩坑记录

微信小程序组件生命周期的踩坑记录

时间2024-02-01 00:36:03发布访客分类JavaScript浏览237
导读:收集整理的这篇文章主要介绍了微信小程序组件生命周期的踩坑记录,觉得挺不错的,现在分享给大家,也给大家做个参考。 组件生命周期,通常是我们业务逻辑开始的地方。如果业务场景比较复杂,组件生命...
收集整理的这篇文章主要介绍了微信小程序组件生命周期的踩坑记录,觉得挺不错的,现在分享给大家,也给大家做个参考。

组件生命周期,通常是我们业务逻辑开始的地方。

如果业务场景比较复杂,组件生命周期有不符合预期的表现时,

可能会导致一些诡异的业务bug,它们极难复现和修复。

组件 attached 生命周期执行次数

按照通常的理解,除moved/show/hide等生命周期可能多次执行外,

严格意义上与组件加载相关的生命周期,如:created、attached、ready等,每个组件实例应该只执行一次。但是事实真的如此吗?

背景

这个问题的发现,源于我们在小程序的报错日志中,

收到大量类似Cannot redefine PRoPErty: iscomponent的报错。

原因分析

通过变量名可以追溯到我们在代码中的定义方式为:

Component({
 lifetimes: {
 attached() {
 Object.defineProperty(this, 'isComponent', {
 enumerable: true, get() {
 return true }
, }
    );
 }
, }
,}
    );
    

很容易理解,这种错误的起因在于试图给对象重新定义一个不可配置的属性,

具体可以查看MDN上的说明。

可是这个定义是写在attached生命周期当中的,难道说,组件的attached生命周期被触发了两次?

天呐,这怎么可能?

是的,就是这么神奇!

场景还原

该问题并不容易复现,但是通过不断删繁就简、抽丝剥茧,最终还是找到了问题的根源:

在页面onLoad之前,通过setData改变状态触发子组件渲染,该子组件的attached生命周期会被触发两次。

可以通过以下代码复现该场景,或者直接访问小程序代码片段。

页面

// page.jsPage({
 data: {
 showChild2: false, }
, onChild1Attached() {
 this.setData({
 showChild2: true }
    );
 }
,}
    );
    
!-- page.wXMl -->
    child1 bind:attached="onChild1Attached">
    /child1>
child2 wx:if="{
{
 showChild2 }
}
    ">
    /child2>
    

子组件1

与页面一同渲染,并在attached的时候,通过triggerevent,通知页面更新状态并渲染子组件2。

// child1.jsComponent({
 lifetimes: {
 attached() {
     this.triggerEvent('attached');
 }
, }
,}
    );
    
!-- child1.wxML -->
    view>
    child1/view>
    

子组件2

执行了两次attached生命周期,导致报错。

// child2.jsComponent({
 lifetimes: {
 attached() {
 Object.defineProperty(this, 'isComponent', {
 enumerable: true, get() {
 return true }
, }
    );
 }
, }
,}
    );
    
!-- child2.wxml -->
    view>
    child2/view>
    

组件 ready 生命周期的执行时机

小程序官方文档没有明确给出组件生命周期的执行顺序,不过通过打印日志我们可以很容易地发现:

@H_360_106@
  • 在加载阶段,会依次执行:created -> attached -> ready
  • 在卸载阶段,会依次执行:detached
  • 所以,看起来这个顺序貌似应该是:created -> attached -> ready -> detached。

    但是实际情况果真如此吗?

    背景

    有段时间,客服经常反馈,我们的小程序存在串数据的现象。

    例如:A商家的直播展示了B商家的商品。

    原因分析

    串数据发生在多个场景,考虑到数据是通过消息推送到小程序端上的,最终怀疑问题出在Websocket通信上。

    在小程序端,我们封装了一个WebSocket通信组件,核心逻辑如下:

    // socket.jsComponent({
     lifetimes: {
     ready() {
         this.getSocketconfig().then(config =>
     {
         this.ws = wx.connectSocket(config);
         this.ws.onMessage(msg =>
     {
         const data = JSON.parse(msg.data);
         this.onReceiveMessage(data);
     }
        );
     }
        );
     }
    , detached() {
         this.ws &
        &
     this.ws.close({
    }
        );
     }
    , }
    , methods: {
     getSocketConfig() {
         // 从服务器请求 socket 连接配置 return new Promise(() =>
     {
    }
        );
     }
    , onReceiveMessage(data) {
         event.emIT('message', data);
     }
    , }
    ,}
        );
        

    简单说,就是在组件ready时,初始化一个WebSocket连接并监听消息推送,然后在detached阶段关闭连接。

    看起来并没有什么问题,那么就只能从结果倒推可能不符合常理的情况了。

    数据串了 -> WebSocket 消息串了 -> WebSocket 没有正常关闭 -> close有问题/detached未执行/ready在detached之后执行

    场景还原

    此处的实际业务逻辑较为复杂,因此只能通过简化的代码来验证。

    通过不断试验,最终发现:

    组件的 ready 与 detached 执行顺序并没有明确的先后关系。

    可以通过以下代码复现该场景,或者直接访问小程序代码片段。

    页面

    // page.jsPage({
     data: {
     showChild: true, }
    , onLoad() {
     this.setData({
     showChild: false }
        );
     }
    ,}
        );
        
    !-- page.wxml -->
    child wx:if="{
    {
     showChild }
    }
        " />
        

    组件

    组件未ready的时候销毁组件,会先同步执行detached,然后异步执行ready。

    // child.jsComponent({
     lifetimes: {
     created() {
         console.LOG('created');
     }
    , attached() {
         console.log('attached');
     }
    , ready() {
         console.log('ready');
     }
    , detached() {
         console.log('detached');
     }
     }
    ,}
        );
        

    拓展

    即便是将初始化的工作从ready前置到attached阶段,只要有异步操作,仍然可能存在detached先于异步回调执行的情况。

    因此,请不要完全信任在组件detached阶段的销毁操作。

    总结

    到此这篇关于微信小程序组件生命周期踩坑的文章就介绍到这了,更多相关小程序组件生命周期内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

    您可能感兴趣的文章:
    • 详解微信小程序scroll-view横向滚动的实践踩坑及隐藏其滚动条的实现
    • 微信小程序使用npm支持踩坑
    • 微信小程序 slot踩坑的解决
    • 微信小程序踩坑记录之解决tabBar.list[3].selectedIconPath大小超过40kb
    • 微信小程序npm引入vant-weapp的踩坑记录
    • 微信小程序自定义tabBar的踩坑实践记录
    • Echarts在Taro微信小程序开发中的踩坑记录
    • 详解微信小程序框架wepy踩坑记录(与vue对比)
    • 微信小程序开发篇之踩坑记录

    声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

    上一篇: 微信小程序input抖动问题的修复方...下一篇:vite2.0+vue3移动端项目实战详解猜你在找的JavaScript相关文章 html font标签如何设置字体大小?html font标签属性用法介绍2022-05-16vue3+TypeScript+vue-router的使用方法2022-04-16vue3获取当前路由地址2022-04-16如何利用React实现图片识别App2022-04-16JavaScript展开运算符和剩余运算符的区别详解2022-04-16微信小程序中使用vant框架的具体步骤2022-04-16Vue elementUI表单嵌套表格并对每行进行校验详解2022-04-16如何利用Typescript封装本地存储2022-04-16微信小程序中wxs文件的一些妙用分享2022-04-16JavaScript的Set数据结构详解2022-04-16 其他相关热搜词更多phpjavapython程序员loadpost-format-gallery

    若转载请注明出处: 微信小程序组件生命周期的踩坑记录
    本文地址: https://pptw.com/jishu/594688.html
    微信小程序input抖动问题的修复方法 C语言中for语句的执行过程是什么?

    游客 回复需填写必要信息