一、动手实现
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./js/jquery-3.2.1.min.js"></script>
</head>
<body>
<div id='title'></div>
<div id='content'></div>
<script>
function renderApp(newAppState, oldAppState={}) { // 防止 oldAppState 没有传入,所以加了默认参数 oldAppState = {}
if(newAppState == oldAppState) return; // 数据没有变化就不渲染了
console.log('render app...')
renderTitle(newAppState.title, oldAppState.title);
renderContent(newAppState.content, oldAppState.content);
}
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;
}
</script>
<script src="./js/index.js"></script>
</body>
</html>
./js/index.js
//################################ 模拟实现redux核心函数 ################################
//reducer作用:初始化和计算新的 state
// 参数:state(数据)、action(如何修改数据)
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};
}
//################################ 使用方式 ################################
//··········· (1) 定一个 reducer
//stateChanger既充当了获取初始化数据的功能,也充当了生成更新数据的功能
function stateChanger(state, action) {
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;
}
}
//··········· (2) 生成 store
const store = createStore(stateChanger);
let oldState = store.getState() // 缓存旧的 state
//··········· (3) 监听数据变化重新渲染页面
store.subscribe(() => {
const newState = store.getState();
renderApp(newState, oldState);
oldState = newState;
});
//··········· (4) 首次渲染页面
renderApp(store.getState());
//··········· (5) 后面可以随意 dispatch 了,页面自动更新
store.dispatch({ type: 'UPDATE_TITLE_TEXT', text: '《hello React.js》' });
store.dispatch({ type: 'UPDATE_TITLE_COLOR', color: 'blue'});
输出:
二、讲解
1、核心函数createStore
(1)reducer
- 作用:初始化和计算新的 state
- 参数:state(数据)、action(如何修改数据)
(2)subscribe:
- 作用:监听数据,变化重新渲染页面
- 参数:一个函数
(3)dispatch:改变数据的唯一途径,每使用一次dispatch,都会自动自行一遍所有的subscribe,所以页面会自动更新
2、使用核心函数
//······················· (1)定一个 reducer ·······················
function reducer (state, action) {
/* 初始化 state 和 switch case */
}
//······················· (2)传给核心函数,生成 store ·······················
const store = createStore(reducer)
// ·······················(3)监听数据变化重新渲染页面 ·······················
store.subscribe(() => renderApp(store.getState()))
//······················· (4)首次渲染页面 ·······················
renderApp(store.getState())
// ·······················(5)后面可以随意 dispatch 了,页面自动更新 ·····················
store.dispatch(...)