小程序结合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:简单计数器&斗鱼接口调用接口