内容简介:顾名思义,就是可以随时穿越到以前和未来,让应用程序切换到任意时间的状态。我们都知道,一般应用状态都很复杂,创建、维护、修改和弄明白有哪些行为会影响状态都不是一件容易的事儿。整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。并使用纯函数计算下一个应用程序状态(不允许其他途径对 state 进行修改)。这些特征使 Redux 成为了一个可预测 的状态容器,这意味着如果给定一个特定应用程序状态和一个特定操作,那么应用程序的下一个
顾名思义,就是可以随时穿越到以前和未来,让应用程序切换到任意时间的状态。我们都知道,一般应用状态都很复杂,创建、维护、修改和弄明白有哪些行为会影响状态都不是一件容易的事儿。
redux 的解决方案
整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。并使用纯函数计算下一个应用程序状态(不允许其他途径对 state 进行修改)。这些特征使 Redux 成为了一个可预测 的状态容器,这意味着如果给定一个特定应用程序状态和一个特定操作,那么应用程序的下一个状态将始终完全相同。这种可预测性使得实现时间旅行变得很容易。redux 也相应的开发了一个带时间旅行的开发者工具 redux-devtools
就是上面这个东西。下面就让我们跟随例子一起来了解下 redux 时间旅行的工作原理。
阅读要求
- react 基础
- redux 基础,明白 action,reducer,state 的关系。明白 combineReducer 的原理。
开始
项目地址:(github)[ github.com/wuyafeiJS/r… ]
预览:
stateHistory.js
export default {
past: [],
futrue: [],
present: undefined,
gotoState(i) {
const index = i * 1;
const allState = [...this.past, this.present, ...this.futrue];
this.present = allState[index];
this.past = allState.slice(0, index);
this.futrue = allState.slice(index + 1, allState.length);
}
};
复制代码
我们把状态分为三个时间段:过去,现在(只有一个状态),将来。gotoState 函数则是用来做时间旅行的,他的实现方式就是整合所有状态 allState,重新分配,present 前面是 past,后面是 future。
那么我们如何去存放每一次变更的状态呢?我们需要找到一个入口,这个入口必须是每次触发状态变更都会经过的地方。而触发状态变更唯一的方式就是 dispatch(action) ,想想,这样的地方好像只有一个地方,看过 redux 源码的同学肯定就是不陌生,那就是 combineReducer 生成的 reducers 纯函数。 combineReducer 负责整合多个 reducer,最终返回一个能够处理所有 action 的 reducers。让我们大致简单实现一下:
const combineReducer = obj => (state, action) => {
const finalState = {};
for (key in obj) {
finanlState[key] = obj[key](state[key], action);
}
return finalState; // 全局state
};
复制代码
接下来,让我们利用函数式编程的思想加强下 reducers 的功能,让它能记录 state: reducers.js
import stateHistory from './stateHistory';// 引入我们之前声明的history对象
// 原本我们是这样返回reducers的
export default combineReducers({
books: fetchReducer,
displayMode: bookDisplayReducer,
currentStatus: statusReducer,
topic: topicReducer
})
// 改造后如下:
export default history(
combineReducers({
books: fetchReducer,
displayMode: bookDisplayReducer,
currentStatus: statusReducer,
topic: topicReducer
})
);
// 我们用history包裹combineReducer,history实现如下
const history = reducers => (state, aciton) => {
switch (action.type) {
case 'UNDO': // 后退
stateHistory.undo();
break;
case 'REDO': // 前进
stateHistory.redo();
break;
case 'GOTO': // 定点指向
stateHistory.gotoState(action.stateIndex);
break;
default:
const newState = reducer(state, action);
stateHistory.push(newState);// 每次dipatch(action)都会像将状态保存到stateHistory
}
return stateHistory.present; // 返回当前状态
}
复制代码
完善下 stateHistory.js
export default {
...
hasRecord(type) {// 查询是否有过去或者将来的状态
return this[type].length > 0;
},
hasPresent() { // 查询是否有现在的状态
return this.present !== undefined;
},
setPresent(state) {
this.present = state;
},
movePresentToPast() {
this.past.push(this.present);
},
push(currentState) { // 将状态都保存,并更新当前状态
if (this.hasPresent()) {
this.past.push(this.present);
}
this.setPresent(currentState);
},
getIndex() { // 获取当前状态index
return this.past.length;
},
undo() { // 后退
if (this.hasRecord('past')) {
this.gotoState(this.getIndex() - 1);
}
},
redo() { // 前进
if (this.hasRecord('futrue')) {
this.gotoState(this.getIndex() + 1);
}
},
...
};
复制代码
配置 action: actions.js
...
export const redo = () => ({
type: 'REDO'
});
export const undo = () => ({
type: 'UNDO'
});
export const gotoState = stateIndex => ({
type: 'GOTO',
stateIndex
});
复制代码
准备工作都已经做完,接下来咱们直接在 react 组件内加上触发代码即可 components/History.js
const History = ({ past, futrue, present, redo, undo, gotoState }) => {
const styles = {
container: {
marginLeft: '20px',
cursor: 'pointer'
},
link: { textDecoration: 'none' },
input: { cursor: 'pointer' }
};
const RightArrow = () => (
// 前进
<a href="#" style={styles.link} onClick={() => redo()}>
</a>
);
const LeftArrow = () => (
// 后退
<a href="#" style={styles.link} onClick={() => undo()}>
</a>
);
const max = () =>
(past ? past.length : 0) +
(present ? 1 : 0) +
(futrue ? futrue.length : 0) -
1;
const value = () => (past ? past.length : 0);
return (
<span>
<input
type="range"
min={0}
max={max()}
value={value()}
onChange={e => {
gotoState(e.target.value);
}}
style={styles.input}
/>
{past && past.length > 0 ? <LeftArrow /> : null}
{futrue && futrue.length > 0 ? <RightArrow /> : null}
</span>
);
};
复制代码
以上!希望对大家理解 redux 有所帮助。
以上所述就是小编给大家介绍的《redux 时间旅行,你值得拥有!》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 「码农周刊 VIP 会员」,你值得拥有!
- 值得拥有!React的四种优秀甘特图方案
- [译] 30 个 Python 最佳实践和技巧,你值得拥有
- 学习编程语言编码这60个资源和工具值得拥有!
- 开源精粹(第六期):刷题必备的 LeetCode 插件,值得你拥有
- MySQL拼接字符串,GROUP_CONCAT 值得拥有
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
机器学习实践指南
麦好 / 机械工业出版社 / 2014-4-1 / 69.00
《机器学习实践指南:案例应用解析》是机器学习及数据分析领域不可多得的一本著作,也是为数不多的既有大量实践应用案例又包含算法理论剖析的著作,作者针对机器学习算法既抽象复杂又涉及多门数学学科的特点,力求理论联系实际,始终以算法应用为主线,由浅入深以全新的角度诠释机器学习。 全书分为准备篇、基础篇、统计分析实战篇和机器学习实战篇。准备篇介绍了机器学习的发展及应用前景以及常用科学计算平台,主要包括统......一起来看看 《机器学习实践指南》 这本书的介绍吧!