小程序生命周期分析与注册流程回掉

2,610 阅读3分钟

从小程序发布到现在,官方api 变动了好几个版本
首先我们先看一下小程序的生命周期

app.js 为小程序的启动入口文件

onLauch: 小程序初始化回掉,生命周期内只执行一次 onShow: 小程序打开或者从后台唤起时的回调 onHide: 小程序从前台进入后台时 onError: 小程序发生脚本错误,或者 api 调用失败时触发,会带上错误信息

页面生命周期:

onLoad:注册页面的时候执行,只执行一次 onShow: 页面在前台展示时执行,显示一次执行一次 onReady: 页面初次渲染完成时执行,冷启动时不执行 onHide: 页面从前台进入后台 onUnload: 页面注销时执行

个人觉得 小程序app中应该增加一个onUnload周期,页面的销毁现实场景个人还没有使用到

===========================================

下面我们来看一下 小程序的注册流程

针对小程序开发者看下图

1. 检查是否是登陆接口

2. 判断session

3. wx.login--》获取token

4. 执行原有回掉

好处:让后续开发者 忽略登陆流程逻辑

function doLogin(callback, obj) {
    if (obj.isLogin) {
        // 登录接口,直接放过
        // 直接放过,让其走下去
        typeof callback === "function" && callback();
    } else if(session) {
        // 缓存中有session
        if(sessionExpireTime && new Date().getTime() > sessionExpire) {
            // 如果有设置本地session缓存时间,且缓存时间已到
            session = '';
            doLogin(callback, obj);
        } else {
            typeof callback === "function" && callback();
        }
    } else if (logining) {
        // 正在登录中,请求轮询稍后,避免重复调用登录接口
        flow.wait('doLoginFinished', function () {
            doLogin(callback, obj);
        })
    } else {
        // 缓存中无session
        logining = true;
        obj.count++;
        // 记录调用wx.login前的时间戳
        // 执行login 获取code
        obj._loginStartTime = new Date().getTime();
        console.log('wx.login');
        wx.login({
            complete: function () {
                obj.count--;
                // 记录wx.login返回数据后的时间戳,用于上报
                obj._loginEndTime = new Date().getTime();
                if (typeof reportCGI === "function") {
                    reportCGI('wx_login', obj._loginStartTime, obj._loginEndTime, request);
                }
                typeof obj.complete === "function" && obj.count == 0 && obj.complete();
            },
            success: function (res) {
                if (res.code) {
                    var data;
                    // codeToSession.data支持函数
                    // 上传服务器操作
                    if (typeof codeToSession.data === "function") {
                        data = codeToSession.data();
                    } else {
                        data = codeToSession.data || {};
                    }
                    data[codeToSession.codeName] = res.code;

                    obj.count++;
                    requestWrapper({
                        url: codeToSession.url,
                        data: data,
                        method: codeToSession.method,
                        isLogin: true,
                        report: codeToSession.report || codeToSession.url,
                        success: function (s) {
                            session        = s;
                            sessionIsFresh = true;
                            // 如果有设置本地session过期时间
                            if(sessionExpireTime) {
                                sessionExpire = new Date().getTime() + sessionExpireTime;
                                wx.setStorage({
                                    key: sessionExpireKey,
                                    data: sessionExpire
                                })
                            }
                            // 执行回掉
                            typeof callback === "function" && callback();
                            wx.setStorage({
                                key: sessionName,
                                data: session
                            })
                        },
                        complete: function () {
                            obj.count--;
                            typeof obj.complete === "function" && obj.count == 0 && obj.complete();
                            logining = false;
                            flow.emit('doLoginFinished');
                        },
                        fail: codeToSession.fail || null
                    });
                } else {
                    fail(obj, res);
                    console.error(res);
                    // 登录失败,解除锁,防止死锁
                    logining = false;
                    flow.emit('doLoginFinished');
                }
            },
            fail: function (res) {
                fail(obj, res);
                console.error(res);
                // 登录失败,解除锁,防止死锁
                logining = false;
                flow.emit('doLoginFinished');
            }
        })
    }
}
处理页面登陆交互的两种方式

1. app.js 注册回掉函数,进入page 注册这个回掉函数,登陆完成执行app.logincallback

page.js
const app = new getApp()
onLoad(){
    app.loginCallback = () => {
        this.init()
    }
}

这种方式可以,而且具有页面控制的灵活性,但灵活性带来的就是出错的几率会增大很多

2. 在login页面获取登陆的前一个页面,然后登陆完成后刷新前一个页面状态

login.js

werequest.login().then(function(){
    let pages = getCurrentPages();
    let Page = pages[pages.length - 1];//当前页
    let prevPage = pages[pages.length - 2];  //上一个页面
    prevPage.onLoad()
})

个人比较提倡这种方式,因为其他页面只需要处理自己的页面逻辑就可以