flux 介绍
- flux 是一种架构思想,专门解决软件的结构问题。它跟 MVC 架构是同一类东西,但是更加简单和清晰。flux 存在多种实现(至少 15 种)
- Facebook Flux 是用来构建客户端 web 应用的应用架构,它利用单向数据流的方式来组合 react 中的视图组件。它更像一个模式而不是一个正式的框架。
redux
-
redux 是什么
- redux 是一个 JavaScript 容器,用于进行全局的状态管理
- redux 可以让你构建一致化的应用,运行于不同环境,并且易于测试
- redux 除了和 react 一起使用,还支持其他的 js 库(vue 、jQuery、JavaScript 等),而且它体积精悍(只有2kb)
-
redux 三大核心
- 单一数据源头
- state 是只读的
- 使用纯函数(reducers)来执行修改 state,纯函数的好处是可以复用
-
redux 组成
-
state 状态
- 服务器返回的 state
- 当前组件的 state
- 全局的 state
-
action 事件
- 本质是一个 js 对象
- 必须包含 type 属性
- 只是描述了有事情要发生,并没有描述如何去更新 state
-
reducer
- 本质就是一个纯函数
- 响应发送过来的 action
- 函数接收两个参数,第一个参数是初始化 state,第二个参数是发送过来的 action
- state 不能直接修改,需要先进行深复制
- 必须要有 return 返回值,返回值就是新的 state
-
store 仓库对象
- 用来把 action 和 reducer 关联到一起的
- 通过 createStore 来构建 store 仓库
- 通过 subscribe 来注册监听
- subscribe 监听的返回值就是这个监听的解绑函数
- 通过 dispatch 来发送 action
注意:组件销毁时,必须要去取消 subscribe 监听
-
-
redux 使用
- 安装 redux 包
$ npm install redux -S
- 创建 store 对象
// 引入 redux 模块 import { createStore } from 'redux' // state 的初始状态 const initState = { collapsed: false } // reducer:唯一修改 state 的地方,不能影响原来的状态,需要深复制 const reducer = (state = initState, action) => { const newState = {...state} // 深复制原来的状态 switch (action.type) { case 'change_collapsed': newState.collapsed = action.collapsed return newState // 返回新状态 default: return state } } // 创建 store,将 action 和 reducer 关联到一起 const store = createStore(reducer) // 导出 store export default store
- 监听 state 数据
// 利用 subscribe 方法,监听 state 转态 this.unsubscribe = store.subscribe(() => { console.log(store.getState()) })
- 解绑 state 的监听
// 利用监听时候接收的返回值调用进行解绑 componentWillUnmount () { this.unsubscribe() }
- 发送同步 action,修改 state 数据
// 利用 dispatch 方法,发送一个 action,type 必须写 store.dispatch({ type: 'change_collapsed', collapsed: this.state.collapsed })
- 发送异步 action
action 是一个 promise 对象时,需要使用 redux-promise 中间件
import {createStore, applyMiddleware} from 'react-redux' // 安装 redux-promise ,并引入 import promiseMiddleware from 'redux-promise' // state 的初始状态 const initState = { list: [] } // reducer:唯一修改 state 的地方 const reducer = (state = initState, action) => { const newState = {...state} // 深复制原来的状态 switch (action.type) { case 'get_data': newState.list = action.list return newState // 返回新状态 default: return state } } // 创建 store 时,使用中间件 const store = createStore(reducer, applyMiddleware(promiseMiddleware)) // 封装一个异步函数,返回值是一个 promise 对象 const getDate = () => { return axios.get('http://loaclhost:5000/user').then(res => { return { type: 'get_data', list: res.data.list } }) } // 发送 action 时,传入 promise 对象 store.dispatch(getData()) // 发送一个 promise 对象
action 是一个 函数时,需要使用 redux-thunk 中间件
import {createStore, applyMiddleware} from 'react-redux' // 下载处理函数的中间件 redux-thunk ,并引入 import thunkMiddleware from 'redux-thunk' // state 的初始状态 const initState = { list: [] } // reducer:唯一修改 state 的地方 const reducer = (state = initState, action) => { const newState = {...state} // 深复制原来的状态 switch (action.type) { case 'get_data': newState.list = action.list return newState // 返回新状态 default: return state } } // 创建 store 时,使用中间件 const store = createStore(reducer, applyMiddleware(thunkMiddleware)) // 也可以同时使用多个中间件 // const store = createStore(reducer, applyMiddleware(promiseMiddleware,thunkMiddleware)) // action 是一个函数 const getDate = () => { return (dispatch) => { axios.get('http://loaclhost:5000/user').then(res => { dispatch({ type: 'get_data', list: res.data.list }) }) } } // 发送 action 时,传入一个函数 store.dispatch(getData())
- reducer 拆分模块
- reducer 可以拆分多个文件,每个文件中处理单独的 action
import { combineReducers } from"redux" import collapsedReducer from 'xxxx' import listReducer from 'xxxx' // 用 combineReducers 方法将多个子 reducer 组合到一起 const reducer = combineReducers({ collapsed: collapsedReducer, list: listReducer }) // 创建 store const store = createStore(reducer)
// collapsedReduces 文件 const collapsedReducer = (state = false, action) => { switch (action.type) { case 'change_collapsed': return action.collapsed default: return state } } export default collapsedReducer
react-redux
针对 react 封装的一个全局状态管理工具,它是基于 redux 的实现,所以基本的 redux 知识没变,它只是让我们在组件中获取 store 中的 state 和 派发 action 变得简单了
-
安装依赖
$ npm install redux react-redux -S
-
redux 创建 store、reducer 等都一样
-
react-redux 中的两个重要成员(Provider、connect)
- Provider 包裹在根组件最外层,使所有的子组件都可以拿到 state
- Provider 接收 store 作为 props,然后通过 context 往下传递,这样 react 中的任何组件都可以通过 context 获取到 store
- Provider 内部组件如果想要使用 state 中的数据,就必须要用 connect 进行一层包裹封装,换一句话说就是必须要被 connect 进行加强
- connect 就是方便我们能够获取到 store 中的 state,以及派发 action
// 引入 Provider 组件 import { Provider } from 'react-redux' // 引入 store 仓库 import store from 'xxxx' // 使用 Provider 组件包裹根组件 render () { return ( <Provider store={store}> <App /> </Provider> ) }
- connect 使用
import React, { Component } from 'react' // 导入 connect import { connect } from 'react-redux' class Home extends Component { render() { return ( <div> home <button onClick={this.props.sendAction()}>点击发送 action</button> </div> ) } } // 获取 store 中的 state,并传递给被加强的组件 const mapStateToProps = (state) => { // 内部会自动实现订阅 return state // 组件中通过 this.props.state 就可以获取到这里返回的值 } // 发送 action 的,写法一:mapDispatchToProps 函数写法 const mapDispatchToProps = (dispatch) => { return { sendAction: () => { // 发送 action dispatch({ tyep: 'send_action', list: xxxx }) } } } // 写法二: mapDispatchToProps 对象写法, const mapDispatchToProps = { sendAction: () => { // 调用这个方法后,内部会自动调用 dispatch 方法 return { type: 'send_action', list: xxxxx } } } // 使用 connect 包裹要加强的组件,第一个参数是获取 state 的,第二个参数是发送 action 的 export default connect(mapStateToProps, mapDispatchToProps)(Home)
redux devtools 插件的使用
-
在浏览器上安装 redux devtools 插件
-
在创建 store 的时候,配置使用 redux devtools
-
import {createStore, applyMiddleware, compose } from 'react-redux' // 下载处理函数的中间件 redux-thunk ,并引入 import thunkMiddleware from 'redux-thunk' // state 的初始状态 const initState = { list: [] } // reducer:唯一修改 state 的地方 const reducer = (state = initState, action) => { const newState = {...state} // 深复制原来的状态 switch (action.type) { case 'get_data': newState.list = action.list return newState // 返回新状态 default: return state } } // 创建 store 时,使用中间件 // 使用 composeEnhancers 包裹 applyMiddleware 后就可以正常使用 redux devtools 了 const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose const store = createStore(reducer, composeEnhancers( applyMiddleware(promiseMiddleware,thunkMiddleware) )) export default store