小程序结合Redux,对于复杂的小程序,是很好的状态管理利器,
而Redux写起来相对复杂费力,
相比阿里爸爸的Dva.js把各种概念组合成model,
是很容易上手的,
在写小程序的时候,
很希望能够将二者结合到一起,
所以在深夜,
就动起手来了。
主要任务分为如下几点,同时附上代码,
应该不算复杂,很简单而粗暴的实现,
性能方面还没有很深的考量过,
以后再慢慢优化,
欢迎各位大佬提意见
重写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)
},
}
小程序初始化的时候要创建store
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
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)
}
})
}
})
}
DEMO:简单计数器&斗鱼接口调用