zoukankan      html  css  js  c++  java
  • 理解mpvue的生命周期

    mpvue是美团基于vue开发的一个开发小程序的框架,从而以vue的语法来开发小程序。在生命周期上,mpvue同时支持了vue的生命周期和小程序的生命周期,这可能让新上手的同学费解。这篇文章就来讲讲mpvue的混合生命周期。

    一个bug

    在深入之前,先说一个mpvue开发中的常见的坑。假设你在一个页面中有打开了一个弹窗,然后在没有关闭的情况下返回上一页,然后再重新进入时,弹窗依然在那里。按道理说,返回上一页时,弹窗所在的page实例已经被unload了,为什么再次进入弹窗还在呢,这其实是mpvue混合生命周期搞的鬼。

    mpvue的生命周期

    在理解mpvue的生命周期前,我们先看一下官方给出的一张图:

    不得不说这张图做的真心有点糙,mpvue本来就不需要传el这个option,结果还是出现在生命周期图示中。。。将el换成page实例倒是更贴切一些。相信不少同学对mpvue的生命周期还是有点晕的。下面我们重新梳理一下各个钩子在什么时候触发。

    这里以官方的mpvue/mpvue-quickstart项目来演示小程序的生命周期函数到底在什么时候触发,项目代码可以参考官方教程获得。

    console.log

    研究触发过程的做法简单粗暴,就是直接在各个生命周期函数下打console.log。mpvue-quickstart有3个页面,分别是index,counter和logs,下面我们给这3个页面加上如下生命周期函数:

     created() {
        console.log('page index created', this)
      },
      mounted() {
        console.log('mounted', this)
      },
      onLoad() {
        console.log('page index onLoad', this)
      },
      onReady () {
        console.log('page index onReady', this)
      },
      onShow() {
        console.log('onShow', this)
      },
      onUnload() {
        console.log('onUnload', this)
      },
      onHide() {
        console.log('onHide', this)
      },
    
    

    完成后,重新编译小程序,控制台打印的日志如下图,分析可以看出以下结论:

    1. vue的created函数先于小程序onLoad函数调用

    2. 一个页面对应一个vue实例,app也对应一个vue实例(打印出的this)

    3. 在小程序的第一页出现前,已经创建出了所有页面对应的Vue实例。看下图可以看出,在index页面的onLoad触发前,page counter,logs的created函数已经触发。

    4. mounted会在onReady之后触发,这个钩子适用于当页面出现时执行一些过渡效果的情况。

    有同学可能会以为vue的实例是和小程序的page实例一起出现的,然而事实并不是这样。

    vue的实例在页面显示之前就已经被初始化了,也就是在main.js中执行new vue(App)的时候。而小程序的页面则是按需加载的,当用户跳转到那个页面时,page实例才会创建。这个观点同样可以由vue实例下面的$mp属性说明,这个属性关联了vue的实例和小程序页面的实例。

    Tips: 当你需要使用wx.createSelectorQuery() 查询某个元素的位置时,应当放在onReady或者mounted的生命周期中进行,保证位置的准确性

    $mp属性

    这个属性在原生vue中是没有的,它是由mpvue扩展出的属性,可以类比原生vue中的(el。在网页中,)el指向vue驱动的dom元素。而在小程序中,$mp指向vue驱动的page或者app实例。

    下面我们看看index和counter两个页面对应的vue实例下$mp属性的区别:

    当页面load后,(mp为ready状态,并且有page属性指向这个页面实例,而页面还没有load时,)mp属性为register状态,没有page属性。也就是说,空有vue实例,但是并没有page可以给他操作。

    onUnLoad方法调用后,相应页面vue实例还在吗?

    上面是在onUnload生命周期函数下打印的this,可见this也就是vue实例并没有被销毁,而小程序的page实例被销毁了。所以vue内部的状态会被保存,如弹窗打开关闭的状态。假设这个状态由this.showModal控制

    data(){
    return {
        showModal: false// 弹窗为关闭状态
    }
    }
    

    当页面再次被打开时,如果上次页面this.showModal为true,则页面刚出现时弹窗就还是打开的。这就解释了文章一开头的那个问题。所以,如果你希望当页面被关闭时,状态不被保存的话,需要在onUnload方法下处理相关逻辑,或者在onShow时重置data里的状态

    // ...
    onUnload(){
        this.showModal = false
    }
    // 更通用一点
    onUnload() {
        Object.assign(this, this.$options.data())
    }
    

    总结:尽管mpvue同时支持了小程序的生命周期和vue的生命周期,但是两者之间并不是共生共灭的关系。更多阅读可以参考这个官方仓库的issue-同一路由切换时,上一次的页面数据会保留 #140

  • 相关阅读:
    Asp.Net 获取客户端真实IP方法总结
    C# 中英文符号互转(半角全角互转)
    执行git commit命令提示: “Please tell me who you are”的解决方案
    Tools
    VSC
    DevOps
    VSC
    DevOps
    DevOps
    K8S
  • 原文地址:https://www.cnblogs.com/imgss/p/9164924.html
Copyright © 2011-2022 走看看