flux与redux与react-redux

Flux与Redux

Flux 是一种架构思想,专门解决软件的结构问题。它跟MVC架构是同一类东西,但是更加简单和清晰。Flux存在多种实现(至少15种) https://github.com/voronianski/flflux-comparison

Facebook Flux是用来构建客户端Web应用的应用架构。它利用单向数据流的方式来组合React中的视图组件。它更像一个模式而不是一个正式的框架,开发者不需要太多的新代码就可以快速的上手Flux.

Redux最主要是用作应用状态的管理。简言之,Redux用一个单独的常量状态树(state对象)保存这一整个应用的状态,这个对象不能直接被改变。当一些数据变化了,一个新的对象就会被创建(使用actions和reducers),这样就可以进行数据追踪,实现时光旅行。

redux介绍以及三大原则

学习文档

redux是什么

  1. redux是一个专门用作状态管理的JS库(不是react插件库)
  2. 它可以用在react,angular,vue等项目中,但基本与react配合使用
  3. 作用:集中式管理react应用中多个组件共享的状态

什么情况下需要使用redux

  1. 某个组件的状态,需要让其他组件可以随时拿(共享)
  2. 一个组件需要改变另一个组件的状态(通信)
  3. 总体原则:能不用就不用,如果不用比较吃力才考虑使用

三大原则

  1. state以单一对象存储在store对象中
  2. state只读(每次都返回一个新对象)
  3. 使用纯函数 reducer执行state更新

redux工作流

redux原理图

redux的三个核心概念

1.action

  1. 动作的对象

  2. 包含2个属性

  • type:标识属性, 值为字符串, 唯一, 必要属性

  • data:数据属性, 值类型任意, 可选属性

  1. 例子:{ type: ‘ADD_STUDENT’,data:{name: ‘tom’,age:18} }

2.reducer

  1. 用于初始化状态、加工状态。

  2. 加工时,根据旧的state和action, 产生新的state的纯函数

3. store

  1. 将state、action、reducer联系在一起的对象

  2. 如何得到此对象?

    1. import {createStore} from ‘redux’
    2. import reducer from ‘./reducers’
    3. const store = createStore(reducer)
  3. 此对象的功能?

    1. getState(): 得到state
    2. dispatch(action): 分发action, 触发reducer调用, 产生新的state
    3. subscribe(listener): 注册监听, 当产生了新的state时, 自动调用

redux的核心API

1. createstore()

作用:创建包含指定reducer的store对象

2.store对象

  1. 作用: redux库最核心的管理对象

  2. 它内部维护着:

    1. state
    2. reducer
  3. 核心方法:

    1. getState()
    2. dispatch(action)
    3. subscribe(listener)
  4. 具体编码:

    1. store.getState()

    2. store.dispatch({type:’INCREMENT’, number})

    3. store.subscribe(render)

3.applyMiddleware()

作用:应用上基于redux的中间件(插件库)

4.combineReducers()

作用:合并多个reducer函数

reducer扩展

如果如果不同的action所处理的属性之间没有联系,我们可以把 Reducer 函数拆分。不同的函数负责处理不同属性,最终把它们合并成一个大的 Reducer 即可。

1
2
3
4
import {combineReducers} from "redux"; 
const reducer = combineReducers({ a: functionA, b: functionB, c: functionC })
访问:
(state)=>{ return { kerwinstate:state.a (不同的命名空间) } }

redux中间件

在redux里,action仅仅是携带了数据的普通js对象。action creator返回的值是这个action类型的

对象。然后通过store.dispatch()进行分发。同步的情况下一切都很完美,但是reducer无法处理异

步的情况。

那么我们就需要在action和reducer中间架起一座桥梁来处理异步。这就是middleware。

1.redux-thunk (store.dispatch参数可以是一个function)
1
2
3
4
import thunk from 'redux-thunk'; 
import {applyMiddleware} from "redux";
const store = createStore(fetchReducer, applyMiddleware(thunk));
const getComingSoon = ()=>{ //进行异步请求 return (dispatch,store)=>{ } }
2.redux-promise (store.dispatch参数可以是一个promise对象)
1
2
3
4
import promiseMiddleware from 'redux-promise'; 
const store = createStore(fetchReducer, applyMiddleware(thunk,promiseMiddleware));
const getComingSoon = ()=>{ //进行异步请求
return axios.get(`****`).then(res=>{ return { type:"cominglist", info:res.data.data }}) }

Redux DevTools Extension

https://github.com/zalmoxisus/redux-devtools-extension

1
2
3
import { createStore, compose} from 'redux' 
import reducer from './reducer'
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; const store = createStore(reducer, /* preloadedState, */ composeEnhancers()) export default store

react-redux

react-redux模型图

1.容器组件与UI组件

UI组件

  • 只负责 UI 的呈现,不带有任何业务逻辑
  • 没有状态(即不使用this.state这个变量)
  • 所有数据都由参数(this.props)提供
  • 不使用任何 Redux 的 API

容器组件

  • 负责管理数据和业务逻辑,不负责 UI 的呈现
  • 带有内部状态
  • 使用 Redux 的 API

2.Provider与connect

React-Redux 提供Provider组件,可以让容器组件拿到state。

1
2
3
4
5
6
7
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import store from './store'
import App from './App'
const rootElement = document.getElementById('root')
ReactDOM.render( <Provider store={store}> <App /> </Provider>, rootElement )

React-Redux 提供connect方法,用于从 UI 组件生成容器组件。connect的意思,就是将这两种组件连起来.

1
2
3
4
5
6
import { connect } from 'react-redux' 
import { increment, decrement, reset } from './actionCreators'
// const Counter = ...
const mapStateToProps = (state /*, ownProps*/) => { return { counter:state.counter } }
const mapDispatchToProps = { increment, decrement, reset }
export default connect( mapStateToProps, mapDispatchToProps )(Counter)

3.HOC与context通信在react-redux底层中的应用

1.connect是HOC,高阶组件

2.Provider组件,可以让容器组件拿到state ,使用了context

4.高阶组件构建与应用

HOC不仅仅是一个方法,确切说应该是一个组件工厂,获取低阶组件,生成高阶组件。

  1. 代码复用,代码模块化
  2. 增删改props
  3. 渲染劫持
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Child.js //高阶函数 
function Control(wrappedComponent) {
return class MyControl extends React.Component {
render() {
if (!this.props.data) {
return <div>loading...</div>
}
return <wrappedComponent {...props} />
}
}
}

class MyControlComponent extends React.Component {
render() {
return <div>{this.props.data}</div>
}
}

export default Control(MyComponent); //高阶组件
// Parent.js
import MyControlComponent from "./Child"

<MyControlComponent data = {this.state.value}/>
//在父级传入data是null的时候,这一块儿就只会显示loading...,
//不会显示组件的具体内容,如果data不为null, 就显示真实组件信息。

5.redux持久化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import {persistStore, persistReducer} from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2';
const persistConfig = { key: 'kerwin',
storage: storage,
//localStorage: import storage from 'redux-persist/lib/storage'
//sessionStorage: import storageSession from 'redux-persist/lib/storage/session'
stateReconciler: autoMergeLevel2 //控制在本地存储中,新老状态怎么合并,覆盖?或者合并?
};
//改造reducer
const myPersistReducer = persistReducer(persistConfig, reducer)
//改造store
export const persistor = persistStore(store)

//改造根组件
import React from "react";
import ReactDom from 'react-dom'
import App from "./08-antd-mobile/App";
// import 'antd/dist/antd.css'
import {Provider} from 'react-redux';
import {store,persistor} from "./08-antd-mobile/redux/store";
import {PersistGate} from "redux-persist/integration/react";

ReactDom.render(
<Provider store={store}>
<PersistGate persistor={persistor}>
<App/>
</PersistGate>
</Provider>
,
document.getElementById('root'))