提起 Redux 我们想到最多的应该就是 React-redux 这个库,可是实际上 Redux 和 React-redux 并不是同一个东西, Redux 是一种架构模式,源于 Flux。 React-redux 是 Redux 思想与 React 结合的一种具体实现。
在我们使用 React 的时候,常常会遇到组件深层次嵌套且需要值传递的情况,如果使用 props 进行值的传递,显然是非常痛苦的。为了解决这个问题,React 为我们提供了原生的 context API,但我们用的最多的解决方案却是使用 React-redux 这个基于 context API 封装的库。
本文并不介绍 React-redux 的具体用法,而是通过一个小例子,来了解下什么是 redux。
好了,现在我们言归正传,来实现我们自己的 redux。
首先,我们用 creat-react-app 来创建一个项目,删除 src 下冗余部分,只保留 index.js,并修改 index.html 的 DOM 结构:
# index.html
<div id="root">
<div id="head"></div>
<div id="body"></div>
</div>
我们在 index.js 中创建一个对象,用它来储存、管理我们整个应用的数据状态,并用渲染函数把数据渲染在页面:
const appState = {
head: {
text: '我是头部',
color: 'red'
},
body: {
text: '我是body',
color: 'green'
}
}
function renderHead (state){
const head = document.getElementById('head')
head.innerText = state.head.text;
head.style.color = state.head.color;
}
function renderBody (state){
const body = document.getElementById('body')
body.innerText = state.body.text;
body.style.color = state.body.color;
}
function renderApp (state){
renderHead(state);
renderBody(state);
}
renderApp(appState);
此时运行代码,打开页面,我们可以看到,在 head 中已经出现了红色字体的‘我是头部’,在 body 中出现了绿色字体的‘我是body’。参考 前端手写面试题详细解答
如果我们把 head 和 body 看作是 root 中的两个组件,那么我们已经实现了一个全局唯一的 state 。这个 state 是全局共享的,随处可调用的。
我们可以修改 head 的渲染函数,来看下效果:
function renderHead (state){
const head = document.getElementById('head')
head.innerText = state.head.text + '--' + state.body.text;
head.style.color = state.head.color;
state.body.text = '我是经过 head 修改后的 body';
}
我们看到,在 head 渲染函数中,我们不仅可以取用 body 属性的值,还可以改变他的值。这样就存在一个严重的问题,因为 state 是全局共用的,一旦在一个地方改变了 state 的值,那么,所有用到这个值的组件都将受到影响,而且这个改变是不可预期的,显然给我们的代码调试增加了难度系数,这样的结果是我们不愿意看到的!
现在看来,在我们面前出现了一个矛盾:我们需要数据共享,但共享数据被任意的修改又会造成不可预期的问题!
为了解决这个矛盾,我们需要一个管家,专门来管理共享数据的状态,任何对共享数据的操作都要通过他来完成,这样,就避免了随意修改共享数据带来的不可预期的危害!
我们重新定义一个函数,用这个函数充当我们的管家,来对我们的共享数据进行管理:
function dispatch(state, action) {
switch (action.type) {
case 'HEAD_COLOR':
state.head.color = action.color
break
case 'BODY_TEX