createStore
react组件更新一定是 setState触发的,
props的改变,也是父级调用了 setSatte,子级的 props改变了
// 创建一个仓库function createStore(reducer) {let store // createStore 不提供初始状态,默认 undefinedlet eventPool = [];// 返回当前的 storefunction getState() {return store}/*** dispatch派发一个动作,规定想要修改的状态* 约定:只能通过派发动作的方式来修改 store** action 要对 store仓库里面的状态做什么操作?* action就是一个普通的对象,至少有一个 type属性,表示动作的类型* 约定:参数都再放在 payload里面*/function dispatch(action) {store = reducer(store, action)eventPool.forEach(r => {if(typeof r === 'function') r()})}// subscribe方法每次调用都会返回一个取消订阅的方法function subscribe(listener) {eventPool.push(listener)return () => {// 调用一次后就删除eventPool = eventPool.filter(r => r !== listener)}}// createStore时,先派发一个动作初始化 state,返回一个默认的 storedispatch({type: '@@TYPE/REDUX_INIT'})return { getState, dispatch, subscribe }}export default createStore
reducer
reducer方法修改 store,返回一个新的 store
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';const initState = {title: {color: 'red',text: '标题'},content: {color: 'green',text: '默认的内容'}}// reducer提供一个初始的参数 state,必须要在 createStore内部调用一次 dispatchfunction reducer(state = initState, action) {const { type, color, text} = actionswitch(type) {case UPDATE_TITLE_COLOR:return {...state,title: {...state.title, color}}case UPDATE_TITLE_TEXT:return {...state,title: {...state.title, text}}case UPDATE_CONTENT_COLOR:return {...state,content: {...state.content, color}}case UPDATE_CONTENT_TEXT:return {...state,content: {...state.content, text}}default:return state}// return newState}
createStore(reducer)
import createStore from './createStore'// 通过 dispatch派发动作去修改 storeconst {getState, dispatch, subscribe} = createStore(reducer)render()function render() {renderApp(getState())}const unsubscribe = subscribe(render) // 订阅事件,store改变,重新执行 render()// 无效,不能先渲染,缺点:store改变不能重新渲染// 例如:多个组件订阅,一个组件修改后,其他组件不重新渲染// dispatch({type: UPDATE_TITLE_COLOR, color: '#90f'})// dispatch({type: UPDATE_CONTENT_TEXT, text: '一树春伸万花开'})// 优化:需要重新 getState渲染,再次优化:dispatch自动渲染,发布订阅模式// renderApp(getState())setTimeout(() => {dispatch({type: UPDATE_TITLE_COLOR, color: '#90f'})dispatch({type: UPDATE_CONTENT_TEXT, text: '一树春伸万花开'})unsubscribe() // 取消订阅,后面的就不执行了dispatch({type: UPDATE_CONTENT_TEXT, text: '万紫千红总是春'})}, 1000)
App

function renderApp(store) {const { title, content } = storerenderTitle(title)renderContent(content)}function renderTitle(data) {const title = document.getElementById('title');const { text, color } = data;title.innerHTML = text;title.style.color = color;}function renderContent(content) {const main = document.getElementById('main')const { text, color } = content;main.innerHTML = textmain.style.color = color;}
