成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Redux原理分析

cooxer / 2631人閱讀

摘要:原理分析是什么很多人認為必須要結合使用,其實并不是的,是狀態(tài)容器,只要你的項目中使用到了狀態(tài),并且狀態(tài)十分復雜,那么你就可以使用管理你的項目狀態(tài),它可以使用在中,也可以使用中在中,當然也適用其他的框架。

Redux原理分析

Redux是什么

很多人認為redux必須要結合React使用,其實并不是的,Redux 是 JavaScript 狀態(tài)容器,只要你的項目中使用到了狀態(tài),并且狀態(tài)十分復雜,那么你就可以使用Redux管理你的項目狀態(tài),它可以使用在react中,也可以使用中在Vue中,當然也適用其他的框架。
一.redux的工作原理

先上圖(圖片源于網(wǎng)絡)

首先我們找到最上面的state

在react中state決定了視圖(ui),state的變化就會調用React的render()方法,從而改變視圖

用戶通過一些事件(如點擊按鈕,移動鼠標)就會像reducer派發(fā)一個action

reducer接收到action后就會去更新state

store是包含了所有了state,可以把他看做所有狀態(tài)的集合

當然,現(xiàn)在可能看不懂這在瞎說啥,但是等把這篇文章看完再來這個圖,和這段話,就會有恍然大明白的感覺

1.action

action本質上就是一個對象,它一定有一個名為type的key 如{type: "add"},{type: "add"}就是一個action
但是我們只實際工作中并不是直接用action ,而是使用action創(chuàng)建函數(shù),(千萬別弄混淆),
顧名思義action創(chuàng)建函數(shù)就是一個函數(shù),它的作用就是返回一個action,如:

function add() {
    return {type: "add"}
}
2.reducer

reducer其實就是一個函數(shù),它接收兩個參數(shù),第一個參數(shù)是需要管理的狀態(tài)state,第二個是action。reducer會根據(jù)傳入的action的type值對state進行不同的操作,然后返回一個新的state,而不是在原有state的基礎上進行修改,但是如果遇到了未知的(不匹配的)action,就會返回原有的state,不進行任何改變

function reducer(state = {money: 0}, action) {
    //返回一個新的state可以使用es6提供的Object.assign()方法,或擴展運算符(此方法需要babel-preset-state-3支持)
    switch (action.type) {
        case "+":
            return Object.assign({}, state, {money: state.money + 1});
        case "-":
            return {...state, ...{money: state.money - 1}};
        default:
            return state;
    }
}
3.store

你可以把store想成一個狀態(tài)樹,它包含了整個redeux應用的所有狀態(tài)。
我們使用redux提供的createStore方法生成store

import {createStore} from "redux";
const store = createStore(reducer);

store提供了幾個方法供我們使用,下面是我們常用的3個:

store.getState();//獲取整個狀態(tài)樹
store.dispatch();//改變狀態(tài),改變state的唯一方法
store.subscribe();//訂閱一個函數(shù),每當state改變時,都會去調用這個函數(shù)

接下來演示一個redux的完整應用,并且說明這三個方法該怎么用

import {createStore} from "redux";

//給初始狀態(tài)一個默認值:{money: 0}
function reducer(state = {money: 0}, action) {
    //返回一個新的state可以使用es6提供的Object.assign()方法,或擴展運算符(此方法需要babel-preset-state-3支持)
    switch (action.type) {
        case "+":
            return Object.assign({}, state, {money: state.money + 1});
        case "-":
            return {...state, ...{money: state.money - 1}};
        default:
            return state;
    }
}

//action創(chuàng)建函數(shù),返回了一個action
function add() {
    return {type: "+"}
}

function subtraction() {
    return {type: "-"}
}

//創(chuàng)建單一狀態(tài)樹
const store = createStore(reducer);

console.log(store.getState());//{money: 0},初始的狀態(tài),沒有任何改變(通過getState來獲取目前的狀態(tài))

//store通過dispatch這個方法,并且傳入action作為參數(shù),對store進行了改變
store.dispatch(add());
console.log(store.getState());//{money: 1},reducer接受到了 "+" 這個命令,就撿到了一塊錢

store.dispatch(subtraction());
console.log(store.getState());//{money: 0},reducer接受到了 "-" 這個命令,又掉了一塊錢

store.dispatch({type:"我是來搗亂的"});
console.log(store.getState());//{money: 0},reducer接受到了一個不識別命令,返回原有的state

這個時候我們就會發(fā)現(xiàn)幾個問題:

每次狀態(tài)改變的時候我們都要console.log()才能知道改變后的狀態(tài),

action的type實際上就是一個字符串,如果我們需要進行項目維護,更改type的值,就需要在多處進行修改,變得十分麻煩。

這個時候我們就可以使用store.subscribe()來訂閱一個事件,代替我們在每次dispatch后都要console.log()后才能知道改變后的狀態(tài)

function listen() {
    console.log(store.getState());
}

store.subscribe(listen);

將type維護成常量,這樣我們在日后的維護過程中只需要對常量進行維護就可以了,我們目前這個demo使用到type的地方太少可能感覺不到,可是在實際項目中這個方法卻非常的實用

const ADD = "+", SUBTRACTION = "-";

我們優(yōu)化后的代碼如下:

import {createStore} from "redux";

//定義常量方便維護
const ADD = "+", SUBTRACTION = "-";

//給初始狀態(tài)一個默認值:{money: 0}
function reducer(state = {money: 0}, action) {
    //返回一個新的state可以使用es6提供的Object.assign()方法,或擴展運算符(此方法需要babel-preset-state-3支持)
    switch (action.type) {
        case ADD:
            return Object.assign({}, state, {money: state.money + 1});
        case SUBTRACTION:
            return {...state, ...{money: state.money - 1}};
        default:
            return state;
    }
}

//action創(chuàng)建函數(shù),返回了一個action
function add() {
    return {type: ADD}
}

function subtraction() {
    return {type: SUBTRACTION}
}

//打印改變后的狀態(tài)
function listen() {
    console.log(store.getState());
}

//創(chuàng)建單一狀態(tài)樹
const store = createStore(reducer);

//訂閱listen,每次dispatch后都會執(zhí)行l(wèi)isten,從而打印狀態(tài)(只有在執(zhí)行dispatch后才會執(zhí)行,狀態(tài)初始化的時候并不會執(zhí)行)
store.subscribe(listen);

console.log(store.getState());//初始的狀態(tài),沒有任何改變

//store通過dispatch這個方法,并且傳入action作為參數(shù),對store進行了改變
store.dispatch(add());
store.dispatch(subtraction());
store.dispatch({type: "我是來搗亂的"});

/*控制臺的打印結果如下:
{money: 0}
{money: 1}
{money: 0}
{money: 0}*/

補充:
一個應用只能有一個store,這個時候就會有一個問題 ,如果有多個reducer分別來處理不同的狀態(tài),而createStore是能接受一個reducer,這個時候我們就需要redux提供的combineReducers方法來將多個reducer結合成一個reducer

import {combineReducers} from "redux";

const reducerFamily=combineReducers({
    reduceSon,
    reduceDaughter,
    reducerFather,
    reducerMother
})
const store = createStore(reducerFamily);
二.在React中使用redux

如果會react,那么也一定知道creact-react-app這個官方腳手架工具,首先使用creact-react-app創(chuàng)建一個項目,然后刪除src目錄下所有文件,接下來就可以愉快的敲代碼了。

在src下創(chuàng)建三個文件
index.js

import React from "react"
import ReactDOM from "react-dom"
import {createStore} from "redux"
//引入我們的reducer和action創(chuàng)建函數(shù)
import {reducer, add, subtraction} from "./index.redux"
import App from "./App"

//創(chuàng)建store
const store = createStore(reducer);

//store.subscribe方法接受的參數(shù)是一個函數(shù),
// 所以將ReactDOM.render方法寫在一個函數(shù)內(nèi)
function listen() {
    //將store,action創(chuàng)建函數(shù)分別以屬性的方式傳遞給子組件App
    ReactDOM.render(,
        document.querySelector("#root"));
}

//因為剛進入頁面沒有dispatch操作改變store,
// 所以listen不會執(zhí)行,我們需要手動調用一次
listen();

//重點,改變了store,頁面就會重新渲染,
// 可以試試不寫這行代碼會是怎樣的效果
store.subscribe(listen);

App.js

import React from "react"

export default class App extends React.Component {
    render() {
        //從屬性中獲取store,action創(chuàng)建函數(shù)
        const {store, add, subtraction} = this.props;
        //獲取state
        let state = store.getState();
        return 

我有{state.money}元

{/*通過store.dispatch方法改變store,從而頁面也會改變*/}
} }

index.redux.js

//定義常量方便維護
const ADD = "+", SUBTRACTION = "-";

//給初始狀態(tài)一個默認值:{money: 0}
export function reducer(state = {money: 0}, action) {
    //返回一個新的state可以使用es6提供的Object.assign()方法,或擴展運算符(此方法需要babel-preset-state-3支持)
    switch (action.type) {
        case ADD:
            return Object.assign({}, state, {money: state.money + 1});
        case SUBTRACTION:
            return {...state, ...{money: state.money - 1}};
        default:
            return state;
    }
}

//action創(chuàng)建函數(shù),返回了一個action
export function add() {
    return {type: ADD}
}

export function subtraction() {
    return {type: SUBTRACTION}
}

效果圖

這樣我們就將redux和react結合了起來但是這樣我們可能會覺得麻煩,因為我們要將store和action創(chuàng)建函數(shù)傳給子組件,當我們的action比較多時,子組件比較多時,就需要將store和大量的action創(chuàng)建函數(shù)一層層的多次傳遞下去。這樣就會十分麻煩,因此我們就可以使用react-redux這個庫來幫助我們實現(xiàn)這個麻煩的過程

三.react-redux的使用 1.Provider

react-redux給我們提供了一個Provider組件,我們可以把這個組件寫在最外層,這樣被Provider包裹的所有組件都可以通過props來獲取state,無論組個組件藏得多么深。
Provider組件只接受一個屬性,那就是store

那么我們index.js的代碼就變成下面這樣了:

import React from "react"
import ReactDOM from "react-dom"
import {createStore} from "redux"
import {Provider} from "react-redux"
import {reducer} from "./index.redux"
import App from "./App"

//創(chuàng)建store
const store = createStore(reducer);

ReactDOM.render(
    
        
    ,
    document.querySelector("#root"));
2.connect

當然,只有Provider組件是不夠的,我們還需要connect來幫助我們獲取state和action,沒錯,connect就是幫助我們獲取state和action的

那么問題就來了,我們的組件可不是需要項目中所有的state和action,只需要其中的一部分就可以了,所以connect會接受兩個參數(shù),第一個參數(shù)它可以幫我們篩選state,第二個參數(shù)可以幫我們篩選action。
我們可以把這兩個參數(shù)寫成函數(shù)的形式,
參數(shù)1,

function mapStateToProps(state) {
    return {
        money: state.money
    }
}

參數(shù)2,

function actionCreators() {
    return {
        subtraction,
        add
    }
}

我們可以發(fā)現(xiàn)這兩個函數(shù)都是返回了一個對象,第一個函數(shù)返回了我們需要的state,第二個函數(shù)返回了我們需要的action創(chuàng)建函數(shù)

那么app.js 的代碼就變成這樣了:

import React from "react"
import {connect} from "react-redux"
import {add, subtraction} from "./index.redux"

class App extends React.Component {
    render() {
        //因為connect的原因,state和action我們已經(jīng)可以從屬性中獲取了
        const {money, add, subtraction} = this.props;

        return 

我有{money}元

{/*這個時候不需要我們dispatch了*/}
} } //connect所需要的參數(shù) //函數(shù)返回的我們需要的狀態(tài),我們需要money,就從state中取出money //假如我們還需要house,就增加一個house:state.house function mapStateToProps(state) { return { money: state.money } } //connect需要的第二參數(shù) //返回我們需要的action創(chuàng)建函數(shù) function actionCreators() { return { subtraction, add } } //上面兩個函數(shù)返回的都是對象 //通過connect將state和action創(chuàng)建函數(shù)當做屬性傳遞給組件 export default App = connect(mapStateToProps, actionCreators())(App);

如果熟悉es6裝飾器的語法那就更好了,可以使我們的代碼變得更優(yōu)雅
app.js

import React from "react"
import {connect} from "react-redux"
import {add, subtraction} from "./index.redux"

@connect(
    state => ({money: state.money}),
    {
        subtraction,
        add
    })
export default class App extends React.Component {
    render() {
        //因為connect的原因,state和action我們已經(jīng)可以從屬性中獲取了
        const {money, add, subtraction} = this.props;

        return 

我有{money}元

{/*這個時候不需要我們dispatch了*/}
} }

看到這里再回頭看看最開始圖片,就能搞清楚redux的工作流程究竟是怎樣的。

文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://systransis.cn/yun/105959.html

相關文章

  • Redux原理分析

    摘要:調用鏈中最后一個會接受真實的的方法作為參數(shù),并借此結束調用鏈??偨Y我們常用的一般是除了和之外的方法,那個理解明白了,對于以后出現(xiàn)的問題會有很大幫助,本文只是針對最基礎的進行解析,之后有機會繼續(xù)解析對他的封裝 前言 雖然一直使用redux+react-redux,但是并沒有真正去講redux最基礎的部分理解透徹,我覺得理解明白redux會對react-redux有一個透徹的理解。 其實,...

    sumory 評論0 收藏0
  • redux原理分析

    摘要:介紹是一個針對應用的可預測的狀態(tài)管理器。中的設計模式裝飾者模式定義裝飾者模式用于給對象動態(tài)地增加職責。連接操作不會改變原來的組件類,而是返回一個新的已與連接的組件類。的這行代碼表示它對的數(shù)據(jù)進行訂閱。 redux介紹 redux是一個針對JavaScript應用的可預測的狀態(tài)管理器。 redux中的設計模式 裝飾者模式 定義:裝飾者模式用于給對象動態(tài)地增加職責。 我們來看看redux最...

    jubincn 評論0 收藏0
  • 【源碼解析】redux-thunk

    摘要:的返回值是函數(shù),這個函數(shù)經(jīng)調用,傳入?yún)?shù),之后會在中間件鏈上進行傳遞,只要保證每個中間件的參數(shù)是并且將傳遞給下一個中間件。 了解了Redux原理之后,我很好奇Redux中間件是怎么運作的,于是選了最常用的redux-thunk進行源碼分析。 此次分析用的redux-thunk源碼版本是2.2.0,redux源碼版本是3.7.2。并且需要了解Redux原理 redux中間件都是由redu...

    simpleapples 評論0 收藏0
  • redux源碼分析

    摘要:背景如今在如此復雜的前端交互和邏輯中,如果是單靠框架,,是遠遠不夠的,還需要一個對內(nèi)部的數(shù)據(jù)狀態(tài)進行管理的機制才行,而對于這種數(shù)據(jù)管理機制如今較為熱門是主要有幾個,,這次主要講述的就是對源碼進行分析。 由于這段時間一直很忙,所以本想六月初研究完redux源碼就寫一篇博客記錄一下自己的心得,但一直現(xiàn)在才空閑出來,廢話不多說了,直接說主題吧。 背景:如今在如此復雜的前端交互和邏輯中,如果是...

    Sike 評論0 收藏0
  • 基于react+react-router+redux+socket.io+koa開發(fā)一個聊天室

    摘要:最近練手開發(fā)了一個項目,是一個聊天室應用。由于我們的項目是一個單頁面應用,因此只需要統(tǒng)一打包出一個和一個。而就是基于實現(xiàn)的一套基于事件訂閱與發(fā)布的通信庫。比如說,某一個端口了,而如果端口訂閱了,那么在端,對應的回調函數(shù)就會被執(zhí)行。 最近練手開發(fā)了一個項目,是一個聊天室應用。項目雖不大,但是使用到了react, react-router, redux, socket.io,后端開發(fā)使用了...

    NusterCache 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<