小程序的一些小知識總結

小程序很多方法都是異步的原因

剛接觸小程序的時候,發現很多微信提供的api都是異步的,如路由跳轉,設置和讀取緩存,還有獲取節點信息等微信的api,都是異步的,需要傳入回調函數才能獲得結果,在我們正常的前端開發中,這些都不是異步的,當時很奇怪爲什麼是這樣的,最近看了微信的一個開發教程之後,總算是明白了。微信小程序開發教程

小程序的底層架構是雙線程模式,邏輯層和渲染層是分開的兩個線程,渲染層指的就是渲染wxml和wxss,邏輯層指的是執行js文件,兩個線程分開運行,通過微信客戶端進行通信,調用微信的api的時候其實就是執行js的線程和微信客戶端通信
下圖是微信官方文檔裏渲染頁面的一個流程圖
clipboard.png

注意事項:
上述說了,小程序的渲染層和邏輯層是分開的兩個線程,執行js邏輯的只有一個線程,所以在js裏聲明瞭的函數,只要有調用,就算頁面卸載了,最終都會執行,所以要注意的是,一些interval,或者一些註冊的其他函數,如果不想在頁面離開後繼續執行的話,在頁面卸載的時候要註銷掉。

發佈和訂閱模式

先補充一個知識點:在小程序的appjs的onLaunch裏,給全局變量wx添加的屬性,是全局有效的,能在其他頁面中調用,比如:

onLaunch: function () {
    wx.aaa = '123456'; 
    wx.bbb = function () { console.log('541521') }
}


onLoad: function () {
    console.log(wx.aaa);
    wx.bbb();
}

之前對發佈和訂閱一直沒什麼概念,但是多學點東西總沒壞處,近期自己花了點時間專門看了一下,大概明白了一點。

訂閱:訂閱就是在某個地方註冊一個自定義的事件,供其他地方調用
發佈:觸發已經訂閱的函數

下面是我寫的一個方法,可能會有一些bug,但是目前沒有發現,要是有問題的話歡迎交流一下


var MyEvent = (function () {
  // 聲明方法
  var pub, sub, remove;

  // 訂閱緩存記錄
  var subCache = {};
  // 發佈緩存記錄
  var pubCache = {};
  // 參數緩存
  var paramCache = {};

  // 訂閱事件
  sub = function (key, fn) {
    if (!subCache[key]) {
      subCache[key] = [];
    }
    // 添加到訂閱緩存中
    subCache[key].push(fn);
    // 如果有發佈記錄,則直接執行函數
    if (pubCache[key]) {
      if (paramCache[key]) {
        fn.apply(null, paramCache[key]);
      } else {
        fn.apply(null);
      }
      pubCache[key] = undefined;
    }
  };
  pub = function () {
    var key = Array.prototype.shift.call(arguments);
    var fns = subCache[key];
    // 沒有訂閱過,則將參數緩存,待訂閱的時候直接執行
    if (!fns || fns.length === 0) {
      pubCache[key] = true;
      paramCache[key] = Array.prototype.slice.call(arguments, 0);
      return;
    }
    // 有訂閱記錄,則直接執行
    for (let fn of fns) {
      fn.apply(null, arguments);
    }
  };
  remove = function (key) {
    // 把所有的緩存全部清除
    subCache[key] = undefined;
    pubCache[key] = undefined;
    paramCache[key] = undefined;
  };
  return {
    pub: pub,
    sub: sub,
    remove: remove
  };
})();

module.exports = MyEvent;

使用方法如下:
在appjs裏引入MyEvent,並掛載在wx對象上

App({
  onLaunch: function () {
    const MyEvent = require('myEvent的路徑');
    wx.myEvent = MyEvent;
  }
})

在其中頁面頁面1的onShow裏訂閱test1事件,發佈test2事件

onLoad: function(){
    wx.myEvent.sub('test1', function () {
        console.log('test1');
    });
},
onShow: function () {
    wx.myEvent.pub('test2', 'test2' + new Date().getTime());
}

在頁面2的onLoad事件裏,發佈test1事件,訂閱test2事件

onLoad: function(options) {
    wx.myEvent.pub('test1');
    wx.myEvent.sub('test2', function(a){
      console.log(a);
    });
}

一. 在頁面1的時候,執行了訂閱test1事件,發佈了test2事件,但是test1沒有發佈,訂閱的事件不會執行,test2事件沒有訂閱,也不會執行。

二. 從頁面1跳轉到頁面2,發佈了test1事件,直接執行之前已經註冊好的test1事件,訂閱test2事件,因爲有test2的發佈事件,訂閱之後直接執行,結果是打印一次test1,打印一次test2。

三. 從頁面2返回到頁面1,執行onShow事件,再次發佈test2事件,打印一次test2

四. 從頁面1到頁面2,發佈了test1事件,事件test2重複訂閱了,訂閱了兩次,打印一次test1。

五. 從頁面2返回頁面1,發佈test2,因爲test2事件訂閱了兩次,所以打印了兩次test2,所以要注意在不需要的地方把事件註銷。

在頁面2的onUnload事件裏把事件test2註銷掉,在從頁面2回到頁面1的時候,事件test2已經註銷了,不會再執行。

onUnload: function() {
    wx.myEvent.remove('test2');
}

原理和用法說明:
原理:
全局只有一個wx對象,將myEvent掛載在wx上,所以全局也只有一個wx.myEvent對象,myEvent裏用到了閉包,訂閱的函數和參數都有保存在內存裏,所以能實現訂閱和發佈的功能。
目前事件訂閱是用的數組存儲,可實現同一個事件訂閱多次,如果不需要的話可自行修改成只能訂閱一次的方法。
用法:
一般用於跨頁面的操作,比如在某個頁面訂閱某個事件,在另一份頁面執行了某項操作之後,發佈該事件,會直接執行訂閱的事件,實現頁面間的一些數據傳遞。
還有也可用於異步請求,先訂閱某個事件,異步請求數據,請求數據回來之後,再發布。

待補充......

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章