Redux實現數據統一管理 詳解

1、什麼是Redux

Redux 是React生態中重要的組成部分。很多人都說,簡單的應用可以不用此工具。但是我個人認爲,中小型應用使用的話,可以使文件結構更加規範,代碼可讀性更強。因爲React提出將展示組件與容器組件分離的思想,所以降低了React 與Redux之間的耦合度。
在這裏插入圖片描述
Redux是一個流行的JavaScript框架,爲應用程序提供一個可預測的狀態容器。Redux基於簡化版本的Flux框架,Flux是Facebook開發的一個框架。在標準的MVC框架中,數據可以在UI組件和存儲之間雙向流動,而Redux嚴格限制了數據只能在一個方向上流動。 見下圖:

圖片描述

在Redux中,所有的數據(比如state)被保存在一個被稱爲store的容器中 → 在一個應用程序中只能有一個。store本質上是一個狀態樹,保存了所有對象的狀態。任何UI組件都可以直接從store訪問特定對象的狀態。要通過本地或遠程組件更改狀態,需要分發一個action分發在這裏意味着將可執行信息發送到store。當一個store接收到一個action,它將把這個action代理給相關的reducerreducer是一個純函數,它可以查看之前的狀態,執行一個action並且返回一個新的狀態。

Redux的運行原理

img

store中重要的方法

img

2、配置Redux

配置Redux開發環境的最快方法是使用create-react-app工具。在開始之前,確保已經安裝並更新了nodejsnpm

npm install redux

創建store目錄,在store目錄下新建index.js文件,鍵入以下內容:

import {createStore} from 'redux';
import reducer from './reducer';

const store = createStore(reducer);

export default store;

在store目錄下創建reducer.js文件,鍵入以下內容:

const defaultState = {
    inputValue:'',
    list:[]
}

//reducer可以接收state,但是不能修改state
export default (state = defaultState,action) => {
    return state;
}

在組件中就可以使用store的數據

import React,{Component} from 'react';
import store from './store/index';

class TodoList extends Component{

    constructor(props){
        super(props);
        this.state = store.getState();
        this.handleStoreChange = this.handleStoreChange.bind(this);
        store.subscribe(this.handleStoreChange);
    }
    
    handleStoreChange(){
        this.setState(store.getState());
    }

    render(){
        return (
            <div>
                <input type='text' value={this.state.inputValue}/>
                <button onClick={this.handleClick}>提交</button>
                <ul>
                    {this.state.list.map((item,index)=>{
                        return (
                            <li key={index}>{item}</li>
                        );
                    })}
                </ul>
            </div>
        );
    }
}

export default TodoList;

3、TodoList案例

TodoList.js

import React,{Component} from 'react';
import store from './store/index';
import {DELETE_TODO_ITEM,CHANGE_INPUT_VALUE,ADD_TODO_ITEM} from './store/actionType'

class TodoList extends Component{

    constructor(props){
        super(props);
        this.state = store.getState();
        this.handleChange = this.handleChange.bind(this);
        this.handleStoreChange = this.handleStoreChange.bind(this);
        this.handleClick = this.handleClick.bind(this);
        store.subscribe(this.handleStoreChange);

    }

    handleChange(e){
        const action = {
            type:CHANGE_INPUT_VALUE,
            value:e.target.value
        }
        store.dispatch(action);
    }

    handleStoreChange(){
        this.setState(store.getState());
    }

    handleClick(){
        const action = {
            type:ADD_TODO_ITEM
        }
        store.dispatch(action);
    }

    handleClickItem(index){
        const action = {
            type:DELETE_TODO_ITEM,
            index:index
        }
        store.dispatch(action);
    }

    render(){
        return (
            <div>
                <input type='text' value={this.state.inputValue} onChange={this.handleChange} />
                <button onClick={this.handleClick}>提交</button>
                <ul>
                    {this.state.list.map((item,index)=>{
                        return (
                            <li key={index} onClick={this.handleClickItem.bind(this,index)}>{item}</li>
                        );
                    })}
                </ul>
            </div>
        );
    }
}

export default TodoList;

store/index.js

import {createStore} from 'redux';
import reducer from './reducer';

const store = createStore(reducer);

export default store;

store/reducer.js

import {DELETE_TODO_ITEM,CHANGE_INPUT_VALUE,ADD_TODO_ITEM} from './actionType'

const defaultState = {
    inputValue:'',
    list:[]
}

//reducer可以接收state,但是不能修改state
export default (state = defaultState,action) => {
    console.log(state,action);
    if(action.type === CHANGE_INPUT_VALUE){
        const newState = state;
        newState.inputValue = action.value;
        return newState;
    }
    if(action.type === ADD_TODO_ITEM){
        const newState = state;
        newState.list.push(newState.inputValue);
        newState.inputValue = '';
        return newState;
    }
    if(action.type === DELETE_TODO_ITEM){
        const newState = state;
        newState.list.splice(action.index,1);
        return newState;
    }
    
    return state;
}

store/actionType.js

export const CHANGE_INPUT_VALUE = 'change_input_value'
export const ADD_TODO_ITEM = 'add_todo_item'
export const DELETE_TODO_ITEM = 'delete_todo_item'

核心API:

  • createStore 創建store
  • store.dispatch 派發action,把數據上傳到Store中
  • store.getState 獲取store中所有的數據內容,但是Store中的數據發生變化時,組件不會知道
  • store.subscribe 監聽Store中的數據變化,Store中的數據一旦發生變化,該方法就會被執行
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章