git clone https://github.com/reduxjs/redux.git
import createStore from './redux/createStore';
import combineReducers from './redux/combineReducers';
import compose from './redux/compose';
import applyMiddleware from './redux/applyMiddleware';
import bindActionCreators from './redux/bindActionCreators';
export {
createStore,
combineReducers,
applyMiddleware,
bindActionCreators,
compose
};
修改 redux 源码适配微信小程序!
import { createStore, applyMiddleware } from '../weapp-redux/index'
import reducer from './reducers/index';
const store = createStore(reducer)
export default store;
import { combineReducers } from '../../weapp-redux/index';
import { commonCart } from './cart';
import { goodsDetail } from './goodsDetail';
import { integralZone } from './integralZone';
import { collect } from './collect';
export default combineReducers({
commonCart,
goodsDetail,
integralZone,
collect
})
import {
UPDATE_COLLECT_LIST,
CHECK_COLLECT_STATUS_GOODS
} from '../constants/actionTypes'
const defaultState = {
list: [],
goodsCollectStatus: {}
}
export const collect = (state = defaultState, action) => {
switch (action.type) {
case UPDATE_COLLECT_LIST:
return { ...state, list: action.list };
case CHECK_COLLECT_STATUS_GOODS:
return { ...state, goodsCollectStatus: action.status}
default:
return state;
}
}
// 收藏商品
// 收藏列表更新
export const UPDATE_COLLECT_LIST = 'UPDATE_COLLECT_LIST_GOODS';
// 删除收藏商品
export const DELETE_COLLECT_GOODS = 'DELETE_COLLECT_GOODS';
// 添加收藏商品
export const ADD_COLLECT_GOODS = 'ADD_COLLECT_GOODS';
// 收藏状态查询
export const CHECK_COLLECT_STATUS_GOODS = 'CHECK_COLLECT_STATUS_GOODS';
import * as integral from './integralZone';
import * as goodsDetail from './goodsDetail';
import * as collect from './collect';
export default {
integral,
collect,
goodsDetail
}
注意此处暴露接口命名最好和reducers中保持一直,这样不易名字混淆!
import store from '../index'
import axios from '../../request/axios'
import {
UPDATE_COLLECT_LIST,
CHECK_COLLECT_STATUS_GOODS
} from '../constants/actionTypes';
export function updateCollectList(list){
store.dispatch({
type: UPDATE_COLLECT_LIST,
list
})
}
export function checkCollectStatusGoods(status){
store.dispatch({
type: CHECK_COLLECT_STATUS_GOODS,
status
})
}
// 获取用户收藏列表
export function getCollectList(){
axios.collectList().then((list = []) => {
if(Array.isArray(list) && list.length){
// 所有收藏商品为未选中
list.forEach(cur => cur.ischeck = false);
updateCollectList(list);
}
}).catch(console.log)
}
// 获取商品收藏状态
export function getGoodsCollectStatus(goodsId, goodsType){
axios.getGoodsCollectStatus({goodsId, goodsType}).then(checkCollectStatusGoods).catch(console.log);
}
// 添加收藏商品
export function addGoodsCollect(goodsId, skid){
return new Promise((resolve, reject) => axios.addGoodsCollect({goodsId, skid}).then(resolve).catch(reject));
}
// 删除收藏商品
export function deleteGoodsCollect(id){
return new Promise((resolve, reject) => axios.delCollect({id}).then(resolve).catch(reject));
}
// app.js
import store from './utils/store/index'
App({
store
})
封装一个类似 react-redux 的中间件;
export default function Provider(store){
const originalPage = Page;
const originalComponent = Component;
}
Page = (config = {}) => {
const { onLoad, onUnload,storeTypes = [] } = config;
config.onLoad = function(opts){
// 监听全局状态数据变化
// 设置页面栈变量$store
this.$store = store;
// 设置监听
if(storeTypes && storeTypes.length > 0){
this.unsubscribe = store.subscribe(() => {
let pageData = {}
storeTypes.forEach(storeType => pageData[storeType] = (store.getState()[storeType] || {}))
this.setData(pageData)
})
// 初始化页面数据
store.dispatch({type: `@@redux/INIT${randomString()}`});
}
// 绑定页面生命周期
onLoad && onLoad.call(this, opts);
}
config.onUnload = function(){
onUnload && onUnload.call(this);
// 页面卸载,取消订阅
this.unsubscribe && this.unsubscribe();
}
originalPage(config);
}
注意:
- 判断 storeTypes,是判断页面是否订阅全局状态的依据,减少订阅的次数,因为每次订阅 listeners,都会收集,执行依次派发, listeners 中的订阅都会执行一次,全部页面和组件都订阅,会消耗性能过大,仅在需要的页面订阅 storeTypes,优化订阅次数。
- 订阅生成,但是如果不取消,就会一直存在,在修改全局状态时,会执行 listeners 中所有的订阅。但是页面卸载后下次进入就会生成新的 id,新的页面,所以需要重新订阅。因此需要在卸载页面的时候取消订阅 this.unsubscribe && this.unsubscribe()。
思考:
- 由于订阅后,派发时所有收集订阅都会执行,是否可以标记订阅,仅通知当前修改的全局状态存在的订阅,不存在当前修改状态的订阅不派发?
- setData 可以只更新部分修改的变量,不修改全部的变量。是否可以通过对比订阅修改前页面当前状态和全局状态进行对比,筛选局部修改变量,进行 setData 修改?
原理和页面一样,此处不多做解释,直接代码。
Component = (config = {}) => {
const { lifetimes = {}, attached:conattached, detached:condetached, storeTypes = [] } = config;
const { attached, detached } = lifetimes;
config.lifetimes = {
attached:function(){
// 监听全局状态数据变化
// 设置页面栈变量$store
this.$store = store;
// 设置监听
if(storeTypes && storeTypes.length > 0){
this.unsubscribe = store.subscribe(() => {
let pageData = {}
storeTypes.forEach(storeType => pageData[storeType] = (store.getState()[storeType] || {}))
this.setData(pageData)
})
// 初始化页面数据
store.dispatch({type: `@@redux/INIT${randomString()}`});
}
// 绑定页面生命周期
attached && attached.call(this);
conattached && conattached.call(this);
},
detached:function(){
detached && detached.call(this);
condetached && condetached.call(this);
// 组件卸载,取消订阅
this.unsubscribe && this.unsubscribe();
}
}
originalComponent(config);
}
import isPlainObject from '../utils/isPlainObject';
const randomString = () => Math.random().toString(36).substring(7).split('').join('.');
const subscribeInit = (config, store, page) => {
let { storeTypes = [] } = config;
// 设置页面栈变量$store
page.$store = store;
// 设置监听
if(storeTypes && storeTypes.length > 0){
page.unsubscribe = store.subscribe(() => {
let pageData = {}
storeTypes.forEach(storeType => pageData[storeType] = (store.getState()[storeType] || {}))
page.setData(pageData)
})
// 初始化页面数据
store.dispatch({type: `@@redux/INIT${randomString()}`});
}
}
export default function Provider(store){
if(!store && typeof store !== 'object'){
throw new Error(`Expected the root store to be a object.`)
}
const originalPage = Page;
const originalComponent = Component;
Page = (config = {}) => {
const { onLoad, onUnload } = config;
config.onLoad = function(opts){
// 监听全局状态数据变化
subscribeInit(config, store, this);
// 绑定页面生命周期
onLoad && onLoad.call(this, opts);
}
config.onUnload = function(){
onUnload && onUnload.call(this);
// 页面卸载,取消订阅
this.unsubscribe && this.unsubscribe();
}
originalPage(config);
}
Component = (config = {}) => {
const { lifetimes = {}, attached:conattached, detached:condetached } = config;
const { attached, detached } = lifetimes;
config.lifetimes = {
attached:function(){
// 监听全局状态数据变化
subscribeInit(config, store, this);
// 绑定页面生命周期
attached && attached.call(this);
conattached && conattached.call(this);
},
detached:function(){
detached && detached.call(this);
condetached && condetached.call(this);
// 组件卸载,取消订阅
this.unsubscribe && this.unsubscribe();
}
}
originalComponent(config);
}
return {
Page,
Component
}
}
// collect.js
import {
getCollectList,
addGoodsCollect,
deleteGoodsCollect
} from '../../utils/store/actions/collect'
Page({
storeTypes: ['collect'],
data: {},
onLoad(){
getCollectList();
}
})
// collect.wxml
现货
{{item.goodsname}}
¥{{item.marketprice}}
最高赚{{item.predictAmt}} 元
取消收藏
我的博客,欢迎交流!
我的CSDN博客,欢迎交流!
微信小程序专栏
前端笔记专栏
微信小程序实现部分高德地图功能的DEMO下载
微信小程序实现MUI的部分效果的DEMO下载
微信小程序实现MUI的GIT项目地址
微信小程序实例列表
前端笔记列表
游戏列表