redux手动实现之一初步

Redux 是一种前端新型的架构模式,经常和 React 一起使用,在我们使用 React 的时候基本都要伴随着 Redux , 并使用 react-redux 这个库把这两粘和起来。

需要注意的是,Redux 是一种从 Flux 演变而来的架构模式,它不关注跟哪个库一起用,你可以把它应用到 React 和 Vue,跟 jquery 结合也没有问题。react-redux 就是一种将 Redux 和 React 结合起来的一个库。

关于 Redux 的用法可以去官网上查看,今天主要是来看下 redux 主要解决了什么问题以及怎么解决的。

通过 webstorm 新建一个项目 redux-achieve , 新建 index.html 里面的 body 结构为:

1
2
3
4
<body>
<div id='title'></div>
<div id='content'></div>
</body>

新建 index.js,添加代码,表示应用的状态:

1
2
3
4
5
6
7
8
9
10
const appState = {
title: {
text: "redux",
color: "red",
},
content: {
text: "redux文档内容",
color: "blue"
}
}

然后添加以下函数,将状态渲染到页面上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function renderTitle(title) {
const titleDom = document.querySelector("#title");
titleDom.innerHTML = title.text;
titleDom.style.color = title.color;
}

function renderContent(content) {
const contentDom = document.querySelector("#content");
contentDom.innerHTML = content.text;
contentDom.style.color = content.color;
}

function renderApp(appState) {
renderTitle(appState.title);
renderContent(appState.content);
}

renderApp(appState);

然后打开页面,就会看到

这是一个很简单的页面,一看就明白,但是这个页面有个很大的问题,就是状态数据 appState 是一个全局变量,每个人都可以修改它,如果页面上有很多操作的话,出现问题的时候,很难排查哪一个操作改变了 appState 的值,这也就是常说的尽量避免使用全局变量。但是,很多时候确实需要全局变量来做到不同功能模块之间的数据共享,这是一个需要解决矛盾点。

为了解决这个问题,我们做一些约定,当我们需要修改共享数据的时候,只能通过制定的方法修改,而不能直接去改,以保证出现问题的时候,方便查找问题的根源。所以新建一个 dispatch 函数,专门用来修改数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function dispatch(state, action) {
switch (action.type) {
case "UPDATE_TITLE_TEXT": {
state.title.text = action.text;
break;
}
case "UPDATE_TITLE_COLOR": {
state.title.color = action.color;
break;
}
default:
break;
}
}

dispatch 接收两个参数,一个是要修改的共享数据对象 state ,一个是action,action是一个普通的js对象,action里面必须包含一个 type 以表示想做什么事情,dispatch 通过这个值去执行对应的操作,action其他的属性是可以自定义传入的。

现在所有对于数据的操作都必须通过调用 dispatch 函数来进行,这时排查 bug 就只需要在 dispatch 的 case 里面打上断点就可以调试出来了。dispatch 就像一个单一功能的数据接口,只需要关注 dispatch 所有对 state 数据的操作就都被监控了。

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试</title>
</head>

<body>
<div id='title'></div>
<div id='content'></div>

<script>
const appState = {
title: {
text: "redux",
color: "red",
},
content: {
text: "redux文档内容",
color: "blue"
}
};

function dispatch(state, action) {
switch (action.type) {
case "UPDATE_TITLE_TEXT": {
state.title.text = action.text;
break;
}
case "UPDATE_TITLE_COLOR": {
state.title.color = action.color;
break;
}
default:
break;
}
}

function renderTitle(title) {
const titleDom = document.querySelector("#title");
titleDom.innerHTML = title.text;
titleDom.style.color = title.color;
}

function renderContent(content) {
const contentDom = document.querySelector("#content");
contentDom.innerHTML = content.text;
contentDom.style.color = content.color;
}

function renderApp(appState) {
renderTitle(appState.title);
renderContent(appState.content);
}

renderApp(appState);
// 三秒钟之后,修改标题和标题颜色,并重新渲染
setTimeout(function () {
dispatch(appState, { type: "UPDATE_TITLE_TEXT", text: "Redux是React是好基友" });
dispatch(appState, { type: "UPDATE_TITLE_COLOR", color: "green" });
renderApp(appState);
}, 3000);

</script>
</body>

</html>

参考

http://huziketang.mangojuice.top/books/react/