天天看點

小程式實作全局監聽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即可

歡迎交流,轉載注明出處即可

繼續閱讀