redux的学习实现第一课:理解dispatch对于状态控制的影响
首先,使用create-react-app创建一个新的react项目,将public中的Index.html改为如下结构:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<title>React App</title>
</head>
<body>
<div id="title"></div>
<div id="content"></div>
</body>
</html>
将index.js中的内容删除,并写入如下内容:
let appState = {
title: {
text: '我是标题',
color: 'red'
},
content: {
text: '我是内容',
color: 'blue'
}
};
function renderTitle(title) {
const titleDOM = document.getElementById('title');
titleDOM.innerHTML = title.text;
titleDOM.style.color = title.color;
}
function renderContent(content) {
const contentDOM = document.getElementById('content');
contentDOM.innerHTML = content.text;
contentDOM.style.color = content.color;
}
function renderApp(state) {
renderTitle(state.title);
renderContent(state.content);
}
renderApp(appState);
此时,使用yarn start
启动项目,可以在浏览器中看到如下内容:
问题出现了 此时,我们需要的样式和文本都已经满足需要,但是很明显,这样对于state的直接操作是非常危险的,在renderApp之前可能会有非常多的对于state的操作甚至修改,我们都将其接受了,这对于之后debug是十分不友好的。那么我们需要做的就是尽力避免直接对state修改
所以,在react小书中有这么一段话:
让我们来想办法解决这个问题,我们可以学习 React.js 团队的做法,把事情搞复杂一些,提高数据修改的门槛:模块(组件)之间可以共享数据,也可以改数据。但是我们约定,这个数据并不能直接改,你只能执行某些我允许的某些修改,而且你修改的必须大张旗鼓地告诉我。
如何实现呢?在index.js中添加如下代码:
function dispatch(action) {
switch (action.type) {
case 'CHANGE_TITLE':
appState.title.text = action.text;
break;
case 'CHANGE_TITLE_COLOR':
appState.title.color = action.color;
break;
case 'CHANGE_CONTENT':
appState.content.text = action.text;
break;
case 'CHANGE_CONTENT_COLOR':
appState.content.color = action.color;
break;
default:
break
}
}
关注点:
- 需要借助固定的action.type才能修改唯一对应的功能
- 且不借助dispatch就无法更改state的内容
此时,我们通过dispatch对内容做一些修改
function dispatch(action) {
switch (action.type) {
case 'CHANGE_TITLE':
appState.title.text = action.text;
break;
case 'CHANGE_TITLE_COLOR':
appState.title.color = action.color;
break;
case 'CHANGE_CONTENT':
appState.content.text = action.text;
break;
case 'CHANGE_CONTENT_COLOR':
appState.content.color = action.color;
break;
default:
break
}
}
dispatch({ type: 'CHANGE_TITLE_COLOR', color: 'purple' });
dispatch({ type: 'CHANGE_CONTENT', text: 'content第一次被修改' });
renderApp(appState);
界面内容成功被修改,即使我们像下面这样在renderApp之前对appState进行魔改,都没有关系,因为我们每一次的修改都是通过dispatch进行的,修改都是可控的,这对于debug来说就更为友好。 原来的修改关系如同下图: 而是用了dispacth的修改关系就多了一层修改控制层:
总而言之,就是多个箭头的修改指向一个appState的情况改为了单个箭头的修改指向appState。 此次的完整代码,如下:
let appState = {
title: {
text: '我是标题',
color: 'red'
},
content: {
text: '我是内容',
color: 'blue'
}
};
function renderTitle(title) {
const titleDOM = document.getElementById('title');
titleDOM.innerHTML = title.text;
titleDOM.style.color = title.color;
}
function renderContent(content) {
const contentDOM = document.getElementById('content');
contentDOM.innerHTML = content.text;
contentDOM.style.color = content.color;
}
function renderApp(state) {
renderTitle(state.title);
renderContent(state.content);
}
function dispatch(action) {
switch (action.type) {
case 'CHANGE_TITLE':
appState.title.text = action.text;
break;
case 'CHANGE_TITLE_COLOR':
appState.title.color = action.color;
break;
case 'CHANGE_CONTENT':
appState.content.text = action.text;
break;
case 'CHANGE_CONTENT_COLOR':
appState.content.color = action.color;
break;
default:
break
}
}
dispatch({ type: 'CHANGE_TITLE_COLOR', color: 'purple' });
dispatch({ type: 'CHANGE_CONTENT', text: 'content第一次被修改' });
renderApp(appState);