剛接觸小程序的時候,發現不少微信提供的api都是異步的,如路由跳轉,設置和讀取緩存,還有獲取節點信息等微信的api,都是異步的,須要傳入回調函數才能得到結果,在咱們正常的前端開發中,這些都不是異步的,當時很奇怪爲何是這樣的,最近看了微信的一個開發教程以後,總算是明白了。微信小程序開發教程前端
小程序的底層架構是雙線程模式,邏輯層和渲染層是分開的兩個線程,渲染層指的就是渲染wxml和wxss,邏輯層指的是執行js文件,兩個線程分開運行,經過微信客戶端進行通訊,調用微信的api的時候其實就是執行js的線程和微信客戶端通訊。
下圖是微信官方文檔裏渲染頁面的一個流程圖
git
注意事項:
上述說了,小程序的渲染層和邏輯層是分開的兩個線程,執行js邏輯的只有一個線程,因此在js裏聲明瞭的函數,只要有調用,就算頁面卸載了,最終都會執行,因此要注意的是,一些interval,或者一些註冊的其餘函數,若是不想在頁面離開後繼續執行的話,在頁面卸載的時候要註銷掉。github
先補充一個知識點:在小程序的appjs的onLaunch裏,給全局變量wx添加的屬性,是全局有效的,能在其餘頁面中調用,好比:小程序
onLaunch: function () { wx.aaa = '123456'; wx.bbb = function () { console.log('541521') } } onLoad: function () { console.log(wx.aaa); wx.bbb(); }
以前對發佈和訂閱一直沒什麼概念,可是多學點東西總沒壞處,近期本身花了點時間專門看了一下,大概明白了一點。微信小程序
訂閱:訂閱就是在某個地方註冊一個自定義的事件,供其餘地方調用
發佈:觸發已經訂閱的函數api
下面是我寫的一個方法,可能會有一些bug,可是目前沒有發現,要是有問題的話歡迎交流一下數組
const 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); } // 若是把參數和發佈緩存清除的話,就是隻容許單次執行 // paramCache[key] = []; // pubCache[key] = undefined; } }; pub = function() { var key = Array.prototype.shift.call(arguments); var fns = subCache[key]; var args = Array.prototype.slice.call(arguments, 0); pubCache[key] = true; paramCache[key] = args; if (!fns || fns.length === 0) { return; } // 有訂閱記錄,則直接執行 for (let fn of fns) { fn.apply(null, args); } }; remove = function(key, fn) { if (subCache[key]) { if (fn) { for(let i = 0, len = subCache[key].length; i < len; i++) { if (fn == subCache[key][i]) { subCache[key].splice(i, 1); break; } } } else { // 把全部的緩存所有清除 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裏用到了閉包,訂閱的函數和參數都有保存在內存裏,因此能實現訂閱和發佈的功能。
目前事件訂閱是用的數組存儲,可實現同一個事件訂閱屢次,若是不須要的話可自行修改爲只能訂閱一次的方法。
用法:
通常用於跨頁面的操做,好比在某個頁面訂閱某個事件,在另外一份頁面執行了某項操做以後,發佈該事件,會直接執行訂閱的事件,實現頁面間的一些數據傳遞。
還有也可用於異步請求,先訂閱某個事件,異步請求數據,請求數據回來以後,再發布。
使用例子
在使用發佈和訂閱的方法以前,好比新增地址,從列表頁面跳轉到新增頁面,在新增頁面新增地址成功以後,將新增的地址放到緩存,接着返回列表頁面,使用navigateBack,在列表頁面的onShow裏檢測是否有緩存,有緩存,則從新加載地址列表
使用發佈訂閱的方法以後,能夠在列表頁面的onLoad裏訂閱新增地址的事件,在新增地址頁面,新增以後,發佈一個新增地址事件,列表頁面監聽到有新增地址事件,則新增一個地址,瞬間感受高大上了
用別人的源碼能夠加快開發速度,並且能夠學習別人的源碼
We UI WeUI 是一套同微信原生視覺體驗一致的基礎樣式庫,由微信官方設計團隊爲微信內網頁和微信小程序量身設計,令用戶的使用感知更加統一。這個是一個樣式庫,只提供樣式。
vant-weapp 這個是一個組件庫,裏面封裝了一些經常使用的組件,是有讚的vant組件庫的小程序版本,我的感受用起來仍是挺好用的。
待補充......