全局对象

在小程序中,一个应用由多个页面组成,一个页面由多个组件组成。

app.js就是用来定义全局配置对象, 全局数据对象,全局回调,全局样式及import所有页面。

app.js外表上看来是一个React组件

  • 全局配置对象 config 配置标题栏与tab栏

  • 全局数据对象 globalData

  • 全局回调

    • onGlobalLoad 每个页面在初次加载时就会执行此回调,注意不存在页面级别的onLoad方法
    • onGlobalReady 每个页面在初次渲染后(布局完成)就会执行此回调,注意不存在页面级别的onReady方法
    • onGlobalUnload 每个页面在被销毁时就会调用此方法,注意不存在页面级别的onUnload方法, 其次路由切换导致当前页面隐藏时,页面不一定销毁,只有此页面被踢出页面栈时才会销毁。页面栈一共保存10个页面. 想用页面级别的onUnload方法,可以用componentWillUnmount代替。
    • onGlobalShow 每个页面在显示时就会调用此方法,页面有onShow方法时,也会同时执行此方法
    • onGlobalHide 每个页面在隐藏时就会调用此方法,页面有onHide方法时,也会同时执行此方法
    • onGlobalShare 只有页面组件没有定义onShare/onShareAppMessage方法,才会调用此方法,此方法要求返回对象
    • onCollectLogs 所有click/tap/change/input/blur等核心的与用户行为相关的事件触发时,都会调用这个回调
    • onSendLogs onCollectLogs理应凑够一定数量的日志就会调用此方法,用于上传日
  • 全局样式 自己手动import 'app.scss'import 'app.less'

  • import 所有以 ./pages/ 开头的依赖放到 app.jsonpages 配置项中。

  • 默认我们会把 第一个./pages开头的依赖当作首页

此外,app.js还支持原生的onLaunch, onError, onShow, onHide。

其中onShow, onHide不等同于onGlobalShow, onGlobalHide, 前两者是小程序从前台进入后台或从后台进入前台触发的, 后两者是页面级别的监听方法。由于快应用不支持应用级别的onShow方法,因此不要使用。

在快应用下,它没有onLaunch, onHide, 娜娜奇会在自动转译成 onCreate、onDestroy方法。

import React from '@react';
import './pages/index/index'; //引入所有页面。
import './pages/demo/base/index';
import './pages/demo/native/index/index';
import './app.less';

class Global extends React.Component {
    //全局配置
     config = {
        window: {
            backgroundTextStyle: 'light',
            navigationBarBackgroundColor: '#0088a4',
            navigationBarTitleText: 'mpreact',
            navigationBarTextStyle: '#fff'
        }
    };
    // 全局数据
    globalData = {
        ufo: 'nanachi',//only test
        __storage: {}  //快应用的storage在这里保存一份副本
    };
    onGlobalLoad(){}
    onGlobalReady(){}
    onGlobalUnload(){}
    onGlobalShow(){}
    onGlobalHide(){}
    onGlobalShare(){ 
        return {};
    }
    onCollectLogs(){}
    onHide(){
          var app = React.getApp()
          console.log(app == this)//由于平台的差异性,React.getApp()得到的对象不定是new App的实例
    }
    onGlobalLoad(){
        //快应用需要在每个页面打开的瞬间初始化同步storage API
        //即getStorageSync, setStorageSync, removeStorageSync, clearStorageSync
        let ANU_ENV = process.env.ANU_ENV;
        if ( ANU_ENV === 'quick' ) { 
           React.api.initStorageSync &&
           React.api.initStorageSync(this.globalData.__storage)
        }
    }
    onLaunch() {
        let ANU_ENV = process.env.ANU_ENV;
        if ( ANU_ENV === 'quick' ) { //非快应用的平台在编译阶段会被干掉
            if ( this.$data && typeof global === 'object') {  //针对快应用的全局getApp补丁
                var ref = Object.getPrototypeOf(global) || global;
                var _this = this;
                ref.getApp = function() {
                    return _this;
                };
                this.globalData = this.$def.globalData;
            }
        }
        console.log('App launched');
    }
}

export default App(new Global());

globalData的设计

在我们公司,globalData会将登录信息(微信的getUserInfo, 里面有openId什么),页面的参数, 场景值全部缓存起来,这样以后大家直接访问React.getApp().globalData就能拿到,建议用户们可以模仿。

//app.js
   globalData = {
        systemInfo: {},
        // 页面渲染时间
        _timestamp: 0,
        // 页面留存时间
        _staytime: 0,
        _startimestamp: 0,
        location: {},
        // 外链带入渠道
        bd_origin: '',
        // 小程序内部渠道,路由跳转会自动替换
        hd_origin: '',
        scene: '',
        logs: [] //日志, 满10条就会自动发送后台
    };
    onLaunch(e) {
        this.globalData.scene = e.scene
        if(process.env.ANU_ENV === 'quick') {
            this.onLaunchQuick(e);
        }
        this.onLaunchNormal(e);
    }
    onHide(){
       this.globalData._staytime = Data.now - this.globalData._startimestamp
    }
    async onLaunchNormal(e) {
        // 统计总体停留时长
        this.globalData._startimestamp = +new Date();
        // 这里要把系统信息放到全局 方便日志收集  业务线调用时要使用util下的getSystemInfo
        React.api.getSystemInfo({
            success: res => {
                this.globalData.systemInfo = res;
            }
        });
    }
    onLaunchQuick(e) {
        //针对快应用的全局getApp补丁
        if (this.$data && typeof global === 'object') {
            var ref = Object.getPrototypeOf(global) || global;
            var _this = this;
            this.globalData = this.$def.globalData || {};
            ref.getApp = function() {
                return _this;
            };
        }
        // 统计总体停留时长
        this.globalData._startimestamp = +new Date();
        React.api.getSystemInfo({
            success: res => {
                this.globalData.systemInfo = res;
            }
        });
        // 拿openId 更新token
        user.appLanchInfos();
        // 获取地理位置 埋点所需 百度账号未登录会报错
        React.api.getLocation({
            success: (res) => {
                this.globalData.location = {
                    lat: res.latitude,
                    lgt: res.longitude
                };
            }
        });
        // 将bd_origin存到全局变量内
        const scene = this.globalData.scene;
        if (e.query) {
            // 缓存初始的bdo
            this.globalData.bd_origin = e.query.bd_origin || '';
            this.globalData.hd_origin = e.query.hd_origin || '';
        }
    }

React.getApp()的使用场合

React.getApp()必须放在app.js 或页面组件或普通组件的生命周期钩子里面执行,不要放在全局作用域下执行

快应用可以这样设置跨页面的全局数据 this.$app.$data = {a:1}

其他配置项统一放在config对象中,详细配置列表参见这里

nanachi