小程序結合Redux,對於複雜的小程序,是很好的狀態管理利器,git
而Redux寫起來相對複雜費力,
相比阿里爸爸的Dva.js把各類概念組合成model,
是很容易上手的,github
在寫小程序的時候,
很但願可以將兩者結合到一塊兒,
因此在深夜,
就動起手來了。小程序
主要任務分爲以下幾點,同時附上代碼,
應該不算複雜,很簡單而粗暴的實現,
性能方面尚未很深的考量過,
之後再慢慢優化,
歡迎各位大佬提意見app
重寫connect,把Page和store連接起來性能
const connect = (mapStateToProps) => { const app = getApp() const state = app._store.getState(); const watchMap = mapStateToProps(state); return (opts) => { const onLoad = opts.onLoad; const onShow = opts.onShow; opts.onLoad = function (options) { const page = this; page._watchMap = Object.keys(watchMap); page._query = options; page._updateData = function (newData) { page.setData(newData); }; onLoad(options, app._store.dispatch) } opts.onShow = function () { global._routing_ = false; const app = getApp()._dva_app_; app._history._handler(); onShow() } return { ...opts, data: { ...watchMap }, dispatch: app._store.dispatch } } }
構造適用於小程序的history優化
const history = { _listenHooks: [], _oldPages: [], _handler: () => { const pages = getCurrentPages(); const oldPages = history._oldPages; if (pages.length > 0) { const isBack = pages.length + 1 == oldPages.length; //頁面返回 頁面不斷出棧,直到目標返回頁,新頁面入棧 // console.log(isBack) history._oldPages = pages; const currentPage = {route : pages[pages.length - 1].route , _query : pages[pages.length - 1]._query} if(currentPage.route.indexOf('/') != 0){ currentPage.route = '/' + currentPage.route } const app = getApp(); app._store.dispatch({ type: '@@route/save', payload:{ pathname: currentPage.route, query: currentPage._query, isBack } }) history._listenHooks.forEach((listen) => { listen({ pathname: currentPage.route, query: currentPage._query, isBack }) }) } }, listen: (callback) => { history._listenHooks.push(callback) }, }
小程序初始化的時候要建立storethis
const creatApp = (opts) => { const app = dva.create({ onStateChange: (state) => { // 同步數據到每個頁面 //console.log(state) const pages = getCurrentPages(); pages.forEach((page) => { if (page._watchMap && page._updateData) { page._watchMap.forEach((key) => { if (state[key]) { const upData = {}; upData[key] = state[key]; page._updateData(upData) } }) } }) } }); app._history = history; if (opts.models) { opts.models.forEach((model) => { app.model(model) }) } // 初始化記錄路由數據的模塊 app.model({ namespace: '@@route', state: { pathname: null, query: {}, isBack: false }, reducers: { save(state, { payload }) { return { ...state, ...payload }; }, }, effects: {} }) app.start() opts._store = app._store; opts._dva_app_ = app; return opts; }
如何作到,監聽state變化同步到page,主要運用dva的onStateChange
spa
onStateChange: (state) => { // 同步數據到每個頁面 //console.log(state) const pages = getCurrentPages(); pages.forEach((page) => { if (page._watchMap && page._updateData) { page._watchMap.forEach((key) => { if (state[key]) { const upData = {}; upData[key] = state[key]; page._updateData(upData) } }) } }) }
源碼:GITHUB,歡迎Start與提意見code
DEMO:簡單計數器&鬥魚接口調用接口