React之Redux

  本文簡單的說下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);
相關文章
相關標籤/搜索