[TOC]
## 第一版
```
let appState = {
title:{color:'red',text:'标题'}
,content:{color:'green',text:'内容'}
};
// change(appState);
function renderTitle(title){
// appState = null;
let element = document.querySelector('#title');
element.innerHTML = title.text;
element.style.color = title.color;
}
function renderContent(content){
let element = document.querySelector('#content');
element.innerHTML = content.text;
element.style.color = content.color;
}
function renderApp(state){
renderTitle(state.title);
renderContent(state.content);
}
renderApp(appState);
```
问题:
此时状态是一个全局变量,任何地方都可以改 例如第八行 就会造成毁灭性结果
## 第二版
改进:
增加修改的门槛
```
const UPDATE_TITLE_COLOR = 'UPDATE_TITLE_COLOR';
const UPDATE_TITLE_TEXT = 'UPDATE_TITLE_TEXT';
const UPDATE_CONTENT_COLOR = 'UPDATE_CONTENT_COLOR';
const UPDATE_CONTENT_TEXT = 'UPDATE_CONTENT_TEXT';
// 派发分发的意思
// action动作 动作 描述一下你想干什么,动作是一个普通的js对象,只有一个属性是必须的 type属性 其它属性随意
function dispatch(action){ //{type:UPDATE_TITLE_COLOR,color:'purple'}
switch(action.type){
case UPDATE_TITLE_COLOR:
appState.title.color = action.color;
break;
case UPDATE_TITLE_TEXT:
appState.title.text = action.text;
break;
case UPDATE_CONTENT_COLOR:
appState.content.color = action.color;
break;
case UPDATE_CONTENT_TEXT:
appState.content.text = action.text;
break;
default:
throw new Error('你发给我的指令我不认识或无法处理!');
}
}
setTimeout(function(){
dispatch({type:UPDATE_TITLE_COLOR,color:'orange'});
dispatch({type:UPDATE_CONTENT_TEXT,text:'新内容'});
renderApp(appState)
},2000);
```
问题:
此时我们仍然可以直接修改appState
## 第三版
改进:
定义一个方法,创建一个仓库,这个仓库其实一个对象,只不过可以引用闭包变量
```
function createStore(){
let state = {
title:{color:'red',text:'标题'}
,content:{color:'green',text:'内容'}
};
function dispatch(action){ //{type:UPDATE_TITLE_COLOR,color:'purple'}
switch(action.type){
case UPDATE_TITLE_COLOR:
state.title.color = action.color;
break;
case UPDATE_TITLE_TEXT:
state.title.text = action.text;
break;
case UPDATE_CONTENT_COLOR:
state.content.color = action.color;
break;
case UPDATE_CONTENT_TEXT:
state.content.text = action.text;
break;
default:
throw new Error('你发给我的指令我不认识或无法处理!');
}
}
function getState(){
return JSON.parse(JSON.stringify(state)); //第二层保护
}
return {
getState,dispatch
}
}
let store = createStore();
renderApp(store.getState());
setTimeout(function(){
store.dispatch({type:UPDATE_TITLE_COLOR,color:'orange'});
store.dispatch({type:UPDATE_CONTENT_TEXT,text:'新内容'});
renderApp(store.getState());
},2000);
```
问题:
此时状态和动作都是写死的,createStore无法复用
## 第四版
改进:
将dispatch做成了一个对外接口,让用户可以自定义动作
并将状态的初始化绑定在了reducer上的第一个参数上
```
function createStore(reducer){
let state;
let listeners = [];
function dispatch(action){ //{type:UPDATE_TITLE_COLOR,color:'purple'}
state = reducer(state,action); //会返回一个新状态
}
function getState(){
return JSON.parse(JSON.stringify(state)); //第二层保护
}
dispatch({}); //获取初始状态
return {
getState,dispatch,subscribe
}
}
let initState = {
title:{color:'red',text:'标题'}
,content:{color:'green',text:'内容'}
};
reduce处理的意思 处理器 根据老的状态和拿到的动作 返回新的状态
let reducer = function(state = initState,action){
switch(action.type){
case UPDATE_TITLE_COLOR:
return {...state,title:{...state.title,color:action.color}};
//return 后自动break
case UPDATE_TITLE_TEXT:
return {...state,title:{...state.title,text:action.text}};
case UPDATE_CONTENT_COLOR:
return {...state,content:{...state.content,color:action.color}};
case UPDATE_CONTENT_TEXT:
return {...state,content:{...state.content,color:action.text}};
default:
return state; //返回老状态
}
};
let store = createStore(reducer);
renderApp(store.getState());
setTimeout(function(){
store.dispatch({type:UPDATE_TITLE_COLOR,color:'orange'});
store.dispatch({type:UPDATE_CONTENT_TEXT,text:'新内容'});
renderApp(store.getState());
},2000);
```
问题:
仍然需要我们手动调用render刷新
## 第五版
改进:
用发布订阅来实现自动render刷新
```
function createStore(reducer,preloadedState){
let state = preloadedState;
let listeners = [];
function dispatch(action){ //{type:UPDATE_TITLE_COLOR,color:'purple'}
// 接收到新的动作后u通过老状态 和新动作 计算出新状态
state = reducer(state,action); //会返回一个新状态
// 然后通知所有的监听函数执行
listeners.forEach(cb => {
console.log(1);
cb();
});
}
function getState(){
return JSON.parse(JSON.stringify(state)); //第二层保护
}
dispatch({}); //获取初始状态 //在redux源码中派发的是名为@@redux/init的东东
// 订阅,供外界订阅本仓库中状态的变化,如果状态变化了会执行订阅的逻辑
function subscribe(listener){
listeners.push(listener);
//会返回一个取消订阅函数
return function(){
listeners = listeners.filter(item=>item!=listener);
}
}
return {
getState,dispatch,subscribe
}
}
let initState = {
title:{color:'red',text:'标题'}
,content:{color:'green',text:'内容'}
};
// reduce处理的意思 处理器 根据老的状态和拿到的动作 返回新的状态
let reducer = function(state = initState,action){
switch(action.type){
case UPDATE_TITLE_COLOR:
return {...state,title:{...state.title,color:action.color}};
//return 后自动break
case UPDATE_TITLE_TEXT:
return {...state,title:{...state.title,text:action.text}};
case UPDATE_CONTENT_COLOR:
return {...state,content:{...state.content,color:action.color}};
case UPDATE_CONTENT_TEXT:
return {...state,content:{...state.content,text:action.text}};
default:
return state; //返回老状态
}
};
let store = createStore(reducer); //可以传入初始值 那么此时initStore将会失效
function render(){
renderTitle(store.getState().title);
renderContent(store.getState().content);
}
render();
store.subscribe(render);
let unsubscribe = store.subscribe(render);
setTimeout(function(){
store.dispatch({type:UPDATE_TITLE_COLOR,color:'orange'});
unsubscribe();
store.dispatch({type:UPDATE_CONTENT_TEXT,text:'新内容'});
},2000);
//为了方便action的书写和避免写错,我们一般会写一个函数来生成对应的action 方便检查错误 有报错
function updateTitleColor(color){
return {type:UPDATE_TITLE_COLOR,color}
}
```
- 空白目录
- 01.JSX,了解一下?
- JSX与虚拟DOM
- React
- 02.React文档精读(上)`
- React路由
- 关于BrowserRouter
- 关于Route
- 应用
- 权限认证
- case1
- context
- 新context
- 03.React路由
- 04.Diff
- 05.styled-components
- redux设计思想与API
- redux实现1
- 06.redux2
- 06.redux3
- 关于状态初始化
- saga
- 新版
- 使用saga进行业务逻辑开发
- react-router-redux
- React性能优化
- immutable使用
- 未整理
- FAQ
- 常用中间件
- pureComponent
- 项目相关总结
- antd分尸
- 按需加载
- ReactWithoutJSX
- 我的组件库
- C领域
- 用户接口
- htmlType
- style
- show
- conjure
- grid
- inject
- stop
- 内部接口
- 衍生组件
- Button
- 报错集锦
- ReactAPI
- 类上的那些属性
- prop-types
- React.createElement
- React.cloneElement
- React.Children和props.children
- react元素和react组件关于作为children方面的那些问题
- react组件与虚拟dom
- ref