react 中的状态管理

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

  • redux devtools npm 地址

    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
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值