1.Redux的简单使用
如果下面的代码看不懂,可以看前面的 Redux简单入门 这篇博客。
/*==================action=====================*/
var add=(number)=>{
return{
type:'add',
number:number,
}
}
/*==================reducer=====================*/
var reducer=(state,action)=>{
var {number,type}=action;
switch (type){
case 'add':
return Object.assign({},state,{num:state.num+number,});
default:
return state;
}
}
/*==================store=====================*/
var redux=require('redux');
var initValue={
num:0,
}
var store =redux.createStore(reducer,initValue);
/*==================简单使用====================*/
console.log('初始化的状态树:',store.getState()); // 0
/*1.分发一个 add 事件*/
store.dispatch(add(10) );
console.log('+10后的状态树:',store.getState()); //10
上面的代码主要使用了redux
中的createStore
模块。通过调用createStore(reducer,initValue)
来创建一个store
对象。那么接下来我们看一下createStore(reducer,initValue)
函数的源码:
2.查看创建store对象的源码
/*
这个createStore函数返回了store对象。
暴露了四个接口:dispatch,subscribe,getState,replaceReducer
参数一:reducer ; 参数二:初始化状态树 ; 参数三:store的增强器
*/
;function createStore(reducer, preloadedState, enhancer) {
//...
var currentReducer = reducer;/*将传递进来的redcer赋值给currentReducer*/
var currentState = preloadedState;/*将传进来初始化的状态树赋值给currentState*/
var currentListeners = [];/*定义一个数组存放监听的回调函数*/
//...
/*返回当前的状态树*/
function getState() {
return currentState;
}
/*
添加监听的函数( 订阅 ) ;
返回一个可以移除监听的函数
*/
function subscribe(listener) {
//...
nextListeners.push(listener);/* 把订阅的函数添加到nextListeners数组中 */
/* 返回一个可以移除监听的函数:listener */
return function unsubscribe() {
//...
var index = nextListeners.indexOf(listener);
nextListeners.splice(index, 1);
};
}
/*分发action的函数,返回结果也是该action*/
function dispatch(action) {
//...
try {
//...
/*
调用reducer函数,并把 当前的状态树和action 传递过去
返回当前新的状态树,来更新状态树。
*/
currentState = currentReducer(currentState, action);
} finally {
//...
}
/*更新完状态树后,使用for循环调用所有监听的函数*/
var listeners = currentListeners = nextListeners;
for (var i = 0; i < listeners.length; i++) {
var listener = listeners[i];
listener();
}
return action;
}
/*替换reducer, 从新初始化状态树*/
function replaceReducer(nextReducer) {
//...
currentReducer = nextReducer;
dispatch({ type: ActionTypes.INIT });
}
// 初始化 store 里的 state tree( 默认初始化时自动分发一个action )
dispatch({ type: ActionTypes.INIT });
//返回 store 暴漏出的接口
return _ref2 = {
dispatch: dispatch,
subscribe: subscribe,
getState: getState,
replaceReducer: replaceReducer
}
}
3.手写一个MiniRedux
1.编写MiniRedux的结构
新建一个MiniRedux.js
文件,编写下面代码:
/**
* 创建store对象的函数: createStore
* @param reducer
* @param initState 初始化状态树
* @returns {{dispatch: dispatch, subscribe: subscribe, getState: getState}}
*/
function createStore(reducer,initState) {
var currentReducer = reducer;/*接收传递进来的reducer函数*/
var currentState = initState;/**默认初始化状态树*/
var currentListeners = [];/**所有的监听函数*/
/**
* 分发action函数
*/
function dispatch(action) {
return action;
}
/**
* 添加订阅事件
*/
function subscribe(listener) {
}
/***
* 获取当前的状态树
* @returns {*}
*/
function getState() {
return currentState;
}
/**
* 最终暴露的接口 API
*/
return{
dispatch: dispatch,
subscribe: subscribe,
getState: getState,
}
}
/*ES5 声明函数导出*/
module.exports=createStore;
2.编写一个test.js测试文件
/*==================action=====================*/
var add=(number)=>{
return{
type:'add',
number:number,
}
}
/*==================reducer=====================*/
var reducer=(state,action)=>{
var {number,type}=action;
switch (type){
case 'add':
return Object.assign({},state,{num:state.num+number,});
default:
return state;
}
}
/*==================store=====================*/
/*这里ES5导入自己编写的MiniRedux框架*/
var createStore = require('./MiniRedux');
var initState={
num:0
}
var store = createStore(reducer,initState);
/*1.打印初始化的状态树*/
console.log('初始化的状态树:',store.getState());
控制台打印输出:
初始化的状态树: { num: 0 }
3.编写分发事件的逻辑
/**
* 分发action函数
*/
function dispatch(action) {
if (typeof action.type === 'undefined') {
throw new Error('action 对象必须包含 type属性 ');
}
/**调用传递进来的reducer函数, reducer是一个纯函数。返回新的状态树*/
currentState = currentReducer(currentState, action);
return action;
}
添加测试代码:
// ...
var createStore = require('./MiniRedux');
var initState={
num:0
}
var store = createStore(reducer,initState);
/*1.打印初始化的状态树*/
console.log('初始化的状态树:',store.getState());
/*2.分发一个action事件*/
store.dispatch( add(100) );
console.log('+100后的状态树:',store.getState()); //100
控制台输出:
初始化的状态树: { num: 0 }
+100后的状态树: { num: 100 }
4.添加订阅事件
/**
* 创建store对象的函数
* @param reducer
* @param initState 初始化状态树
* @returns {{dispatch: dispatch, subscribe: subscribe, getState: getState}}
*/
function createStore(reducer,initState) {
var currentReducer = reducer;
var currentState = initState;
var currentListeners = [];
/**
* 分发action函数
*/
function dispatch(action) {
if (typeof action.type === 'undefined') {
throw new Error('action 对象必须包含 type属性 ');
}
/**调用传递进来的reducer函数, reducer是一个纯函数。返回新的状态树*/
currentState = currentReducer(currentState, action);
var listeners = currentListeners;
/**更新状态树之后,马上遍历订阅事件的数组,并调用每一个订阅事件*/
for (var i = 0; i < listeners.length; i++) {
var listener = listeners[i];
/**调用每一个订阅事件*/
listener();
}
return action;
}
/**
* 添加订阅事件
* @param listener 订阅事件
* @returns {unSubScribe} 取消订阅事件
*/
function subscribe(listener) {
if (typeof listener !== 'function') {
throw new Error('listener 不是一个函数');
}
/**把订阅事件添加多数组中去*/
currentListeners.push(listener);
/**
* 返回一个取消订阅的函数
*/
return function unSubScribe() {
/**找到要取消的订阅的函数*/
var index = currentListeners.indexOf(listener);
/**从数组中移出要订阅的函数*/
currentListeners.splice(index, 1);
}
}
/***
* 获取当前的状态树
* @returns {*}
*/
function getState() {
return currentState;
}
/**
* 最终暴露的接口 API
*/
return{
dispatch: dispatch,
subscribe: subscribe,
getState: getState,
}
}
/*ES5 声明函数导出*/
module.exports=createStore;
编写测试代码:
//...
/*==================store=====================*/
var createStore = require('./MiniRedux');
var initState={
num:0
}
var store = createStore(reducer,initState);
/*添加给订阅事件*/
var onChange=function () {
console.log('更新后的状态树:',store.getState());
}
var unSubscribe=store.subscribe(onChange);
/*1.打印初始化的状态树*/
console.log('初始化的状态树:',store.getState());
/*2.分发action事件*/
store.dispatch( add(100) );
store.dispatch( add(100) );
/**取消监听事件*/
unSubscribe(onChange)
store.dispatch( add(100) );
控制台打印输出:
初始化的状态树: { num: 0 }
更新后的状态树: { num: 100 }
更新后的状态树: { num: 200 }