Redux(一) -- redux的使用及其工作原理

前言:

在我们使用react进行开发时,管理不断变化的 state 非常困难。如果一个 model 的变化会引起另一个 model 变化,那么当 view 变化时,就可能引起对应 model 以及另一个 model 的变化,依次地,可能会引起另一个 view 的变化。直至你搞不清楚到底发生了什么。state 在什么时候,由于什么原因,如何变化已然不受控制。

所以我们需要把 state 进行统一管理,这样才能控制每一个state的变化,让我们的程序可读性更强,出错率更低。


一、什么是Redux?

Redux 是一个 JS 库,一个状态容器。

作用: 集中式管理 React 应用中 多个组件共享的状态

(1)它可以和 react,vue,angular 等一起使用,但一般都和 react一起使用 。
(2)Redux 可以 解耦 React(View层)于数据管理和对数据的操作,保持View层的纯净,
	让每一个组件的职责划分更加清楚,同时又降低了React数据传递的难度和不可控性
(3)Redux 采用了中间件机制,既保证了代码的简洁,又增加了可扩展性。

Redux的三大原则:

(1)单一数据源

整个应用的state都被存储到一个状态树里面,并且这个状态树,只存在于唯一的store中

(2)State 是只读的

唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。

(3)使用纯函数来执行修改

为了描述 action 如何改变 state tree ,你需要编写 reducers。

下面就让我们来一步步解析Redux的工作原理,以及关键功能。

二、Redux的工作原理

Redux(一) -- redux的使用及其工作原理_第1张图片

Redux关键功能解析:

1.Store:集中状态管理中心
(1)store就是保存数据的地方,当有数据改变时,store会调用reducer进行处理,完事后通知View层调用getState更新
(2)Redux提供createStore这个函数,用来生成Store,内部接收reducer
import {createStore} from 'redux'
const store=createStore(reducer);
2.View层:由组件构成视图层
(1)接收数据时,调用getState( )接收Store的newState,并重新渲染更新视图
(2)用户操作时,通过事件触发制造action并派发 来通知Store来更新state
// 接收 State
const state=store.getState()
3.ActionCreator:一个工厂函数,负责产生action对象
(1)与View层的事件进行关联,一旦有通知就制造action对象
(2)action = {  
		type: action类型,
		data: 事件携带的数据(可有可无)
	}
const action={
  type:'ADD_TODO',
  payload:'redux原理'
}

在上面代码中,action的名称是ADD_TODO,携带的数据是字符串‘redux原理’,action描述当前发生的事情,这是改变state的唯一的方式 ( 通过action传值 )

4.dispatch:派发action,方法使用了中间件机制
(1)store.dispatch()是view发出Action的唯一办法
(2)store.dispatch接收一个action作为参数,将它发送给store来通知 store调用reducer改变state。
(3)dispatch 时,还可以在中间插入副作用操作(网络请求等),其内部会调用中间件进行处理
const action={
  type:'ADD_TODO',
  payload:'redux原理'
}
store.dispatch(action)
// 或者直接
store.dispatch({
  type:'ADD_TODO',
  payload:'redux原理'
})
5.Reducer:处理action,再把处理完成后的newState返回给Store
(1)接收两个参数(preState, action),第一个参数是之前的旧数据或初始数据,第二个参数是action
(2)处理完的State的引用地址必须为新的内存地址,否则不会触发更新**(重要)
(3)当reducer过多时,可以使用combineReducers进行整合处理

注意:Reducer必须是一个纯函数,只要传入参数相同,返回计算得到的下一个 state 就一定相同。
	 没有特殊情况、没有副作用,没有 API 请求、没有变量修改,单纯执行计算。
const reducer = (preState = initialState, action)=>{
  switch(action.type){
    case ADD_TODO:
        return newState;
    default return state
  }
}
6.Redux整体执行流程
  1. 用户通过事件触发ActionCreator制造action
  2. 同时,用户触发的事件内调用dispatch来派发action
  3. reducer接收action,并处理state返回newState
  4. View层通过getState( )来接收newState并重新渲染视图层

(在我们实际操作时,Store只需要一开始创建就好了,后面我们我们完全不需要操作它)

7.Redux源码

源码解析参考自此

let createStore = (reducer) => {
	//获取状态对象
    let state;
    //存放所有的监听函数
    let listeners = [];
    let getState = () => state;
    //提供一个dispath 方法供外部调用派发action
    let dispath = (action) => {
        //调用管理员reducer得到新的state
        state = reducer(state, action);
        //执行所有的监听函数
        listeners.forEach((item) => item())
    }
    //订阅状态变化事件,当状态改变发生之后执行监听函数
    let subscribe = (listener) => {
        listeners.push(listener);
    }
    dispath();
    return {
        getState,
        dispath,
        subscribe
    }
}
let combineReducers=(renducers)=>{
    //传入一个renducers管理组,返回的是一个renducer
    return function(state={},action={}){
        let newState={};
        for(var attr in renducers){
            newState[attr]=renducers[attr](state[attr],action)

        }
        return newState;
    }
}
export {createStore,combineReducers};

三、使用Redux实现计数器案例

// store.js
import { createStore } from "redux";
import reducer_counter from "./reducer_counter";

const store = createStore(reducer_counter);

export default store;
// constant.js
// 储存常量
export const INCREMENT = 'INCREMENT'
export const DECREMENT = 'DECREMENT'
// action_creator.js
import { INCREMENT, DECREMENT } as constant from './constant'

export const incrementAction = ()=>({type: INCREMENT})
export const decrementAction = ()=>({type: DECREMENT})
// reducer_counter.js
import { INCREMENT, DECREMENT } from './actionType'

// defaultState 可以是任意js类型,但最好还是传入 数组 或 对象
const  defaultState = {count: 0}

// Store收到Action以后,必须返回一个新的state(内存地址要改变),这样view才会发生变化,
const reducer_counter =  (state = defaultState,action) =>{
    switch (action.type) {
    // 根据action.type分别对不同的action进行处理
        case INCREMENT:
            return {count:state.count + 1}
        case DECREMENT:
            return {count:state.count - 1}
        default:
           return state
    }
}

export default reducer_counter
// App.js
import React from 'react'
import store from './store'
import {incrementAction,decrementAction} from './store/action_creator'

class App extends React.Component {
  constructor(){
    super()
    // state就是store里面存储的数据,store里面可以拥有多个state
    // Redux规定一个state对应一个View,只要state相同,view就是一样的,反过来也是一样的
    // 通过store.getState()来从store获取数据
    this.state = store.getState()
    // 订阅state变化,state变化执行更新函数更新视图
    store.subscribe(this.asyncState)
  }
  asyncState = ()=>{
    this.setState(store.getState())
  }
  increment = ()=>{
    // dispatch派发action,参数由action_creator创建
    store.dispatch(incrementAction())
  }
  decrement = ()=>{
    store.dispatch(decrementAction())
  }
  render() { 
    return (
       <div>
          Clicked : { this.state.count} times
          <button onClick={this.increment}>+</button>
          <button onClick={this.decrement}>-</button>
       </div>
    );
  }
}
export default App;

你可能感兴趣的:(Redux数据状态管理,react.js,前端,javascript)