动手实现 Redux(一):优雅地修改共享状态
动手实现 Redux(二):抽离 store 和监控数据变化
动手实现 Redux(三):纯函数(Pure Function)简介
动手实现 Redux(四):共享结构的对象提高性能
动手实现 Redux(五):不要问为什么的 reducer
动手实现 Redux(六):Redux 总结
// 定一个 reducer
function reducer(state, action) {
/* 初始化 state 和 switch case */
if (!state) {
return {
title: {
text: 'React.js 小书',
color: 'red'
},
content: {
text: 'React.js 小书内容',
color: 'blue'
}
}
}
switch (action.type) {
case 'UPDATE_TITLE_TEXT':
return {
...state,
title: {
...state.title,
text: action.text
}
};
case 'UPDATE_TITLE_COLOR':
return {
...state,
title: {
...state.title,
color: action.color
}
};
default:
return state;
}
}
// 生成 store
function createStore(reducer) {
let state = null;
const listeners = [];
const subscribe = (listener) => listeners.push(listener);
const getState = () => state;
const dispatch = (action) => {
state = reducer(state, action);
listeners.forEach((listener) => {
listener();
});
};
dispatch({}); // 初始化 state
return {
getState,
dispatch,
subscribe
}
}
// 生成 store
const store = createStore(reducer);
let oldState = store.getState(); // 缓存旧的state
// 监听数据变化重新渲染页面
store.subscribe(() => {
const newState = store.getState();
renderApp(newState, oldState);
oldState = newState;
});
function renderTitle(newTitle, oldTitle) {
if (newTitle === oldTitle) {
return;
}
console.log('render title...')
const titleDOM = document.getElementById('title');
titleDOM.innerHTML = newTitle.text;
titleDOM.style.color = newTitle.color;
}
function renderContent(newContent, oldContent) {
if (newContent === oldContent) {
return;
}
console.log('render content...')
const contentDOM = document.getElementById('content');
contentDOM.innerHTML = newContent.text;
contentDOM.style.color = newContent.color;
}
function renderApp(newAppState, oldAppState = {}) {
if (newAppState === oldAppState) {
return;
}
console.log('render app...')
renderTitle(newAppState.title, oldAppState.title);
renderContent(newAppState.content, oldAppState.content);
}
// 首次渲染页面
renderApp(store.getState());
// 后面可以随意 dispatch 了,页面自动更新
store.dispatch({type: 'UPDATE_TITLE_TEXT', text: '《React.js 小书》'}); // 修改标题文本
store.dispatch({type: 'UPDATE_TITLE_COLOR', color: 'blue'}); // 修改标题颜色