zoukankan      html  css  js  c++  java
  • react_结合 redux

    Redux 独立的集中式状态管理 js 库 - 参见 My Git

    不是 react 库,可以与 angular、vue 配合使用,通常和 react 用

    yarn add redux

    import {createStore} from "redux"

    const store = createStore(myCounter);    // 1. 核心 API - 参数是 reducer 函数---> 根据现有的状态及 action 返回一个新的状态,给 store 管理

    import {INCREMENT, DECREMENT} from "./action-types"    // 有几个 case,就要定义几个 action 工厂

    export default function myCounter(state=0, action){    // 由 store 内部调用,初始值为 0 ./redux/reducers

    switch(action.type){    // action 一定要有一个 type 属性

    case INCREMENT:{return state+action.numbe;brack;}

    case INCREMENT:{return state+action.numbe;brack;}

    default: return state

    }

    }

    <App store={store}

     

    import {INCREMENT, DECREMENT} from "./action-types"

    export const INCREMENT = "increment";

    export const DECREMENT = "decrement";

    import * as actions from "../redux/actions";

    this.props.store.dispatch(actions.increment(number));    // action creator 产生一个 action 对象,然后 dispatch 这个行为 action

    // 虽然等同于 this.props.store.dispatch({type: INCREMENT, number}); 但是一般不这么做

    // 工厂函数 - 每次调用,返回一个新的对象 - 每次都返回一个 actions

    this.props.store.getState();

    • action

    如果是 对象,则是 同步 action ---- 返回一个对象,描述行为、state 参数

    export const menuTitle = (menuTitle)=>({tyle: SETMENUTITLE, data: menuTitle})

    如果是 函数,则是 异步 action

    返回一个 函数,该函数接收一个 dispatch 参数

    该函数内部进行异步操作,有了结果以后,再 dispatch 同步 action

    export const login = ()=>{

    return dispatch=>{

    // 1. 执行异步代码

    const result = await requestLogin(username, password);

    // 2. 分发同步 action

    if(result.status === 0){

     

    }else{

     

    }

    }

    }

    • reducer

    根据现有的 state 和 action 生成新的 state

    • const store = createStore(myReducer)    // 根据 n 个现有需要管理的 state 和 action 返回一个新的 state,给 store 集中管理
    • store 最核心的 管理对象---- 与 react 的交互就是 更新

    存储状态数据的对象

    维护着 state 和 reducer

    核心方法

    • 获取状态 store.getState()        
    • 更新状态 store.dispatch(action-creator)   

    对象 action

    • 必须有 type 标识属性,值为字符串
    • 可选数据属性,值为任意类型
    • 订阅一个监听函数 subscribe(listener)

    什么时候用 redux?

    某个组件的状态需要共享

    一个组件需要改变全局状态

    一个组件需要改变另一个组件的状态

    总体原则: 能不用就不用,如果不用比较吃力才考虑使用

    不用 redux 时的集中状态管理?

    将多个组件的共用状态放在共同的父组件中

    将状态的相关方法定义在与状态相同的组件中

    官方实例分析?

    redux 编程:

    ---------------------------------------------------------------------------------------------------------

    src/redux/store.js

    import {createStore} from "redux"

    import reducer from "./reducer"

    export default creareStore(reducer);    // 创建 store 对象,内部会第一次自调用 reducer 函数得到一个初始的状态值进行保存

    ---------------------------------------------------------------------------------------------------------

    src/redux/reducer.js

    import {INCREMENT, DECREMENT} form "./action-types"

    export default  function count(state=1 action){    // 管理 count 就可以叫 count,state 本身就是要管理的数据,第一次展示显示 1

    switch(action.type){

    case INCREMENT:{return state+action.number;}

    case INCREMENT:{return state-action.number;}

    default: return state;    // 不做任何处理

    }

    }

    ---------------------------------------------------------------------------------------------------------

    src/redux/actions.js    // 包含 n 个 action-creator 函数

    import {INCREMENT, DECREMENT} form "./action-types"

    export const increate = (number)=>({type: INCREMENT, number});

    export const decreate = (number)=>({type: DECREMENT, number});

    ---------------------------------------------------------------------------------------------------------

    src/redux/action-types.js    // 多个 js 共用

    export const INCREMENT = "increment";

    export const DECREMENT = "decrement";

    ---------------------------------------------------------------------------------------------------------

    src/index.js

    import React from "react"

    import ReactDOM from "react-dom"

    import App from "./App.jsx"

    import store from "./redux/store"

    ReactDOM.render(<App store={store} />, document.getElementById("root"));

    store.subscribe(()=>{

    ReactDOM.ummountComponentAtNode(document.getElementById("root"));    // 先卸载原来的组件

    ReactDOM.render(<App store={store} />, document.getElementById("root"));

    })

    ---------------------------------------------------------------------------------------------------------

    src/App.jsx

    import React, {PureComponent} from "react"

    import * as actions from "./redux/actions"

    export default class App extends PureComponent{

    increment = ()=>{

    const number = +this.refs.numberSelect.value;

    this.props.store,dispatch(actions.increment(number));

    }

    decrement = ()=>{

    const number = +this.refs.numberSelect.value;

    this.props.store,dispatch(actions.decrement(number));

    }

    render(){

    const count = this.props.store.getState();

    }

    }

    问题: react 与 redux 耦合度太强了,直接使用了 store

    解决: 使用 react 的插件库 react-redux ---- 简化 react 中使用 redux

    ----------------------------------------- react 与 redux 的连接--------------------------------------------

    Provider

    向所有容器组件提供 store

    connect(生成 容器组件,负责向 UI 组件传递标签属性

    第一参数: 函数 ---- 一般属性从 state 中获取

    state=>({title: state.menuTitle})

    第二参数: 原始函数/简写对象{actionCreator1, action2}---- 函数属性,执行 dispatch 分发 action-creator

    )(UI组件)

    ---------------------------------------------------------

    src/index.js

    import React from "react"

    import ReactDOM from "react-dom"

    import App from "./App.jsx"

    import store from "./redux/store"

    import {Provider} from "react-redux"

    -------------------------------------------------------------------------------------------------------------------

    src/App.jsx

    import React, {PureComponent} from "react"

    import {connect} from 'react-redux'

    imoprt Counter from "./components/Counter"

    imoprt {increment, decrement]} from "./redux/actions"

    function mapStateToProps(state){    // 读取 state 数据,并将其映射成 UI 组件的一般属性

    return {count: state}

    }

    function mapDispatchToProps(dispatch){    // 为 UI 组件映射函数属性,函数内部必须 dispatch,分发 action,产生新的 state,重新 render

    return {

    incremrnt: number=>dispatch(increment(number))

    decremrnt: number=>dispatch(decrement(number))

    }

    }

     

    export default connect(

    mapStateToProps,    // 用来确定向 UI 组件传递哪一些一般属性 count

    mapDispatchToProps    // 用来确定向 UI 组件传递哪些函数属性 increment、decrement

    )(Counter)        // 用 connect 函数包装一下 App 组件,返回一个新的组件对象

    -------------------------------------------------------------------------------------------------------------------

    src/components/Counter.jsx

    1

    react-redux 将组件分为

    UI 组件

    不会使用任何 redux 相关的语法

    最终,值还是要被 store 管理的 ,getState()、dispatch()、

    容器组件: 通过 connect 包装 UI 组件生成的组件,内部可以看见 store

    1. 向 UI 组件传递一般属性,属性值 会以 state 传递

    传递 状态 以及操作 store  的相关函数到 reducer 中

    2. 属性值函数内部必然执行 dispatch 去分发 action

    最终的简洁写法-------------------------------------------------------------------------------------

    redux 异步编程

    下载 异步中间件 yarn add redux-thunk

    store.js

    import thunk from "redux-thunk"    // 中间件,扩展 redux 使其可以 action-creator 可以返回 函数

    import {createStore, applyMiddleware} from "redux"

    import reducer from "./reducer"

    export default createStore(reducer, applyMiddleware(thunk));

    actions.js 红中增加 异步 action  

    返回的是一个函数,函数会接收一个参数:dispatch

    dispatch函数可以执行异步代码, 有了结果,再分发一个同步的 action

    export const increment = (number)=>({type:"increment", number})

    export const incrementAsync = number=>{

    return dispatch=>{

    setTimeout(()=>{

    dispatch(increment(number))

    }, 1000)

    }

    }

    redux 与 chrome 调试工具

    yarn add redux-devtools-extension

     

     combineReducers()

    纯函数 ---- 同样的输入,得到同样的输出

    不得修改参数    {...state, username: "test"}

    不得调动 系统 I/O 的 API

    不能调动不纯的 Date.now()  或者 Math.random() 等函数

    高阶函数 ---- 参数是函数 或者 返回值是函数

    filter、map、addEventListener、

    高阶组件 ---- 函数接收一个组件,产生的新组件

    connect

    前端项目 和 后台服务器项目 各自独立运行

    会产生 资源未找到 或者 跨域

    • 需要 后台工程师 进行代理服务器配置
    • 或者 将 前端项目 和 后台服务器项目 合并

    前端项目 置于 后台服务器项目的 public

    问题:

    BrowserRouter 传递 state ---- 以致于访问 被置为后台路由处理了

    解决: 

    自定义中间件处理

     

    后台没有一个页面能够处理时,查看是否有前台页面可以返回

    前台路由路径 不能与 后台路由路径 一样

     专门的组件页面 应对 404 和 500 页面

    --------小尾巴 ________一个人欣赏-最后一朵颜色的消逝-忠诚于我的是·一颗叫做野的心.决不受人奴役.怒火中生的那一刻·终将结束...
  • 相关阅读:
    cron生成
    sp_addlinkedserver,Synonym
    上海城市坐标
    评分插件 jquery.raty.js
    ORA-12514: TNS:listener does not currently know of service requested in connect
    ORA-01034: ORACLE not available ORA-27101: shared memory realm does not exist
    工厂模式
    单例模式
    Qt中的Q_OBJECT作用, 以及信号槽
    DDLog-不同颜色打印信息
  • 原文地址:https://www.cnblogs.com/tianxiaxuange/p/10318581.html
Copyright © 2011-2022 走看看