本文简单的说下redux。html
首先这有张网页,里面有文字和内容。redux
<!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>ReactDemo</title> </head> <body> <div id="title"></div> <div id="content"></div> <div id="root"></div> </body> </html>
如今让这个网页经过状态来显示标题和内容。函数
let state = { title:{ color:'red', text:'标题' }, content:{ color:'blue', text:'内容' } } function renderTitle(){ let title = document.querySelector('#title'); title.style.background = state.title.color; title.innerHTML = state.title.text; } function renderContent(){ let content = document.querySelector('#content'); content.style.background = state.content.color; content.innerHTML = state.content.text; } //渲染的方法 function render(){ renderTitle(); renderContent(); } render();
这有个问题,首先状态不能是全局的,也不该该哪一个方法均可以直接更改,这样作很危险,因此须要提供一个更改状态的方法,修改这状态的时候提供一个对象带有type类型的dispath来修改状态。ui
//先定义好须要干那些事情(常量)宏 const CHANGE_TITLE_COLOR = 'CHANGE_TITLE_COLOR'; const CHANGE_CONTENT_TEXT = 'CHANGE_CONTENT_TEXT'; let state = { title:{ color:'red', text:'标题' }, content:{ color:'blue', text:'内容' } } //派发时一个将修改的动做提交过来 //参数{type:'',载荷} function dispatch(action){ //派发的方法,这里要更改的状态 switch(action.type){ case CHANGE_TITLE_COLOR: state.title.color = action.color; break; case CHANGE_CONTENT_TEXT : state.content.text = action.text; break; default: break; } } function renderTitle(){ let title = document.querySelector('#title'); title.style.background = state.title.color; title.innerHTML = state.title.text; } function renderContent(){ let content = document.querySelector('#content'); content.style.background = state.content.color; content.innerHTML = state.content.text; } //渲染的方法 function render(){ renderTitle(); renderContent(); } render(); dispatch({type:CHANGE_CONTENT_TEXT,text:'随便改的'}); render();
可是这么写state仍是能被外人调到,因此就有了Redux里面的store。spa
//先定义好须要干那些事情(常量)宏 const CHANGE_TITLE_COLOR = 'CHANGE_TITLE_COLOR'; const CHANGE_CONTENT_TEXT = 'CHANGE_CONTENT_TEXT'; function createStore(){ let state = { title:{ color:'red', text:'标题' }, content:{ color:'blue', text:'内容' } } let getState = () => state; //派发时一个将修改的动做提交过来 //参数{type:'',载荷} function dispatch(action){ //派发的方法,这里要更改的状态 switch(action.type){ case CHANGE_TITLE_COLOR: state.title.color = action.color; break; case CHANGE_CONTENT_TEXT : state.content.text = action.text; break; default: break; } } //将方法暴露给外面使用 return {dispatch,getState} } let store = createStore(); function renderTitle(){ let title = document.querySelector('#title'); title.style.background = store.getState().title.color; title.innerHTML = store.getState().title.text; } function renderContent(){ let content = document.querySelector('#content'); content.style.background = store.getState().content.color; content.innerHTML = store.getState().content.text; } //渲染的方法 function render(){ renderTitle(); renderContent(); } render(); store.dispatch({type:CHANGE_CONTENT_TEXT,text:'随便改的'}); render();
dispath写到库里面去多个开发者添加屡次仍是很恶心的,因此改改代码,将定义状态和规则的部分抽离到外面去。抽离的状态叫initState,抽离的规则叫reducer(也就是所谓的管理员)。code
//先定义好须要干那些事情(常量)宏 const CHANGE_TITLE_COLOR = 'CHANGE_TITLE_COLOR'; const CHANGE_CONTENT_TEXT = 'CHANGE_CONTENT_TEXT'; let initState = { title:{ color:'red', text:'标题' }, content:{ color:'blue', text:'内容' } } //须要两个参数 老的状态和新传递的动做算出新的状态 //若是想获取默认状态就是调用reducer让每个规则都不匹配将默认值返回 function reducer(state=initState,action){ //reducer是一个纯函数,每次须要返回一个新的状态 switch(action.type){ case CHANGE_TITLE_COLOR: return {...state,title:{...state.title,color:action.color}}; case CHANGE_CONTENT_TEXT : return {...state,content:{...state.content,text:action.text}}; default: return state; } } function createStore(reducer){ let state let getState = () => state; //派发时一个将修改的动做提交过来 //参数{type:'',载荷} function dispatch(action){ //派发的方法,这里要更改的状态 state = reducer(state,action); } dispatch({}) //将方法暴露给外面使用 return {dispatch,getState} } let store = createStore(); function renderTitle(){ let title = document.querySelector('#title'); title.style.background = store.getState().title.color; title.innerHTML = store.getState().title.text; } function renderContent(){ let content = document.querySelector('#content'); content.style.background = store.getState().content.color; content.innerHTML = store.getState().content.text; } //渲染的方法 function render(){ renderTitle(); renderContent(); } render(); store.dispatch({type:CHANGE_CONTENT_TEXT,text:'随便改的'}); render();
咱们发现一个问题,每次dispath以后都得render一下,ok那么咱们就整下,其实就是一个发布订阅,每次dispath时都调用订阅号的方法。htm
//先定义好须要干那些事情(常量)宏 const CHANGE_TITLE_COLOR = 'CHANGE_TITLE_COLOR'; const CHANGE_CONTENT_TEXT = 'CHANGE_CONTENT_TEXT'; let initState = { title:{ color:'red', text:'标题' }, content:{ color:'blue', text:'内容' } } //须要两个参数 老的状态和新传递的动做算出新的状态 //若是想获取默认状态就是调用reducer让每个规则都不匹配将默认值返回 function reducer(state=initState,action){ //reducer是一个纯函数,每次须要返回一个新的状态 switch(action.type){ case CHANGE_TITLE_COLOR: return {...state,title:{...state.title,color:action.color}}; case CHANGE_CONTENT_TEXT : return {...state,content:{...state.content,text:action.text}}; default: return state; } } function createStore(reducer){ let state ; let listeners = []; let subscirbe = (listener)=>{ //订阅 listeners.push(listener); return ()=>{ //再次调用时移除监听函数。 listeners = listener.filter(fn => fn !== listener); } } let getState = () => state; //派发时一个将修改的动做提交过来 //参数{type:'',载荷} function dispatch(action){ //派发的方法,这里要更改的状态 state = reducer(state,action); listeners.forEach(listener=>listener()); } dispatch({}) //将方法暴露给外面使用 return {dispatch,getState,subscirbe} } let store = createStore(); function renderTitle(){ let title = document.querySelector('#title'); title.style.background = store.getState().title.color; title.innerHTML = store.getState().title.text; } function renderContent(){ let content = document.querySelector('#content'); content.style.background = store.getState().content.color; content.innerHTML = store.getState().content.text; } //渲染的方法 function render(){ renderTitle(); renderContent(); } render(); //订阅 store.subscirbe(render) setTimeout(() => { store.dispatch({type:CHANGE_CONTENT_TEXT,text:'随便改的'}); }, 2000) //取消订阅 // let unsub = store.subscirbe(render) // setTimeout(() => { // unsub(); // store.dispatch({type:CHANGE_CONTENT_TEXT,text:'随便改的'}); // }, 2000);