天天看点

小程序实现全局监听globalData数据的状态管理模式

前几天准备回去架构组来着,但是那边新来了个妹子在搞,新项目有还没启动,小程序一直有项目,又没人,一直在小程序的feature-team中,这不又来个几个需求。

其中一个新需求是需要做一个协议更新的功能,即老用户登录后,接口检查一遍协议是否已更新,需要重新同意协议,否则直接退出小程序。

查了一下没有全局组件的说法,问了隔壁老王,老徐有什么比较好的方法,都丢下一句话,写个component然后挨个页面引入,在每个页面做一遍标签引入,然后传值给子组件,子组件observe即可。

按照常规实现我感觉这个改动还挺大的,首先每个页面都得引入标签赋值状态。而我的想法是全部功能在组件内实现,页面只需要用一个标签即可,组件内监听登录态即可,想了一下试试数据劫持的实现模式:

app.js

//  使用数据劫持模式去监听登录状态
  watchLogin(callback, that){
    console.log("this.globalData", this.globalData)
    var obj = this.globalData;
    Object.defineProperty(obj,"isLogon", {
      configurable: true,
      enumerable: true,
      set: function (value) {
        this._isLogon = value;
        console.log('登录状态被赋值',this._isLogon)
        callback(value, that);
      },
      get:function(){
        return this._isLogon
      }
    })
  },
           

组件内:

const app = getApp() //获取应用实例

methods: {
	//登录状态回调
    watchBack(isLogon, that){
      console.log('登录状态数据变化 isLogon', isLogon)
      console.log("watchBack this",this)    // 这里的this是无效的
      console.log("watchBack that",that.data)
      if (isLogon) {
       	...that.methodsName()
      }
    },
}
/*组件生命周期*/
lifetimes: {
   created() {
   },
   attached() {
       console.log("在组件实例进入页面节点树时执行")
       // 调用app中监听登录状态的方法
       app.watchLogin(this.watchBack, this)
   }
}
           

基本就实现了一个全局状态的监听更新,登录状态改变时会自动触发setter,然后触发callback,将setter的value以参数的方式传过来判断一下就可以使用了。

注意:开发过程还需要注意两个问题

  1. Object.defineProperty数据劫持时,如果在setter中直接写

    this.isLogon = value

    ,那么系统会报一个超出最大堆栈大小,

    RangeError: Maximum call stack size exceeded at Object.set [as isLogin]

    ,首先可以确定的是进入死循环了,其实就是在set的时候调用了get,

    this.isLogin = value

    ,无限循环了,解决方式为只需要找一个值替代即可,使用替代值或者屏蔽掉都可以.
  2. 关于this, 在watchBack函数中直接使用

    this.methods...

    这样调用方法是行不通的,watchBack是拿不到this的,会报一个undefined,因为它是回调函数中的this,解决方法:

    app.watchLogin()

    传个this即可

欢迎交流,转载注明出处即可

继续阅读