摘要: 小程序狀態管理。javascript
Fundebug經受權轉載,版權歸原做者全部。html
微信小程序的市場在進一步的擴大,而背後的技術社區仍在摸索着最好的實踐方案。我在幫助Nike,沃爾瑪以及一些創業公司開發小程序後,依舊認爲使用小程序原生框架是一個更高效,穩定的選擇,而使用原生框架惟獨缺乏一個好的狀態管理庫,若是不引入狀態管理則會讓咱們在模塊化,項目結構以及單元測試上都有些捉襟見肘。java
目前相對比較穩健的作法是針對redux或者mobx作一個adaptor應用到小程序中,但這樣須要本身想辦法打包引入外部庫,還要想怎麼去寫這個adaptor,總顯得有些麻煩。因而我迸發出一個想法去寫一個專用於小程序的狀態管理庫,它使用起來足夠簡單而且能夠經過小程序本身的npm機制安裝。git
目前我已經用這個開源庫開發了兩個電商小程序,在提升我開發效率的同時亦保證了程序的性能,因此接下來我想談談這背後的理念以啓發更多開發者嘗試新的解決方案。github
Proxy在小程序中已經獲得了足夠好的支持,目前並無發如今任何iPhone或者Android上不能使用Proxy的狀況。而基於Proxy的狀態管理其實也就是訂閱監聽的模式,一方面監聽數據的變化,另外一方面將這些變化傳達給訂閱的小程序頁面。npm
舉一個比較常見的例子,當一個用戶從本身的主頁進入用戶編輯頁面,而後更改了本身的用戶名點擊保存後,用戶主頁和用戶編輯頁上的用戶名這時候都應該被更新。這背後的程序邏輯則是:更新這個行爲將觸發Proxy去通知狀態管理庫,而後狀態管理庫負責檢查此時還在頁面棧中的全部頁面,更新訂閱了用戶名這個數據的頁面,以下圖:編程
監聽數據變化其實就是監聽各個Store的屬性變化,實現上就是在各個Store前面加了一層Proxy,用更直觀的圖片來表示就是這樣:redux
當一個Store被觀察之後,它的屬性就都變成了Proxy實例,當這個屬性值是Object或者Array的時候,它內部的值也會被包裝成Proxy實例,這樣不管多深層的數據變更都能被監聽到。 而在Proxy的後面,Store的屬性實際上是被另外一套數據(紫色部分)所維護,這套數據不負責監聽,它就是純數據,針對屬性的任何變更最後都會應用到這套數據上來,它的做用是維護和返回最新的數據。小程序
實現細節: https://github.com/wwayne/min...segmentfault
由於小程序每一個頁面的js都是向Page中傳遞一個對象,這就讓咱們有機會包裝這個對象,從而實現:
實現細節: https://github.com/wwayne/min...
當數據被監聽到變化後,咱們須要依次作兩件事,先是找到全部存儲在頁面棧裏的頁面,而後根據各個頁面訂閱的數據來檢查變化,若是有變化就通知這些頁面,從而讓它們去觸發setData更新頁面。
實現細節:https://github.com/wwayne/min...
有了狀態管理庫,如今咱們就來實現一開始舉例的更新用戶信息的操做,咱們的文件路徑以下:
stores/ user.js pages/ userEdit/ index.js index.wxml
1. 首先咱們建立一個Store保存用戶的信息,而且監聽它的變化:
// stores/user.js import { observe } from 'minii' Class UserStore { constructor () { this.name = 'bob' } changeName (name) { this.name = name } } export default observe(new UserStore(), 'user')
2. 接着在咱們的小程序頁面訂閱Store的信息
// pages/userEdit/index.js import { mapToData } from 'minii' import userStore from '../../stores/user' const connect = mapToData(state => (({ myName: state.user.name })) Page(connect({ updateNameToJames () { userStore. changeName('james') } }))
3. 完成,如今能夠在頁面中使用和更新數據了
// pages/userEdit/index.wxml <text>{{ myName }}</text> <button bindtap="updateNameToJames">update name to James</button>
小程序由於有體積的限制,因此我但願在代碼量上也儘可能作到輕量和便捷,因此目前這個狀態管理庫並無太多很複雜的功能,在小程序打包後所佔用的體積也不到1kb,很有點夠用就好的意思。
我也已經用它開發了兩款小程序,在經歷了一段時間的用戶使用後,我也更有信心說這個方案在小程序中是可行的。若是你有任何想法和建議,都歡迎告訴我。
項目Github: https://github.com/wwayne/minii
Hi, 我是wwayne,是一名居住在上海的獨立軟件工程師,我正在開發個人新產品 talk-to-kim, 你能夠在Github 或者專欄 一我的寫代碼找到我
Fundebug專一於JavaScript、微信小程序、微信小遊戲、支付寶小程序、React Native、Node.js和Java線上應用實時BUG監控。 自從2016年雙十一正式上線,Fundebug累計處理了10億+錯誤事件,付費客戶有陽光保險、荔枝FM、掌門1對一、核桃編程、微脈、青團社等衆多品牌企業。歡迎免費試用!