react是视图层框架,redux是数据层框架,管理数据状态和UI状态的JavaScript应用工具
redux - 图1
通俗理解:
image.png

创建store

  • 在src目录下创建/store/index.js ```javascript import {createStore} from ‘redux’ import reducer from ‘./reducer’

// 创建数据存储仓库 const store=createStore(reducer)

export default store

  1. - store目录下创建reducer
  2. ```javascript
  3. const defaultState={
  4. inputValue:'请输入',
  5. listData:[
  6. '早8点开晨会,分配今天的开发工作',
  7. '早9点和项目经理作开发需求讨论会',
  8. '晚5:30对今日代码进行review'
  9. ]
  10. }
  11. export default ((state=defaultState,action)=>{
  12. return state
  13. })

使用store

  1. import React, { Component } from 'react';
  2. import store from '../store/index'
  3. class TodoList extends Component{
  4. constructor(props){
  5. super(props)
  6. //获取state
  7. this.state=store.getState()
  8. }
  9. render(){
  10. return(
  11. <div>
  12. <div>
  13. <Input value={this.state.inputValue} style={{width:250,marginRight:10}}/>
  14. <Button type="primary">增加</Button>
  15. </div>
  16. <List bordered dataSource={this.state.listData}
  17. renderItem={(dataItem)=>(
  18. <List.Item>{dataItem}</List.Item>
  19. )}/>
  20. </div>
  21. )
  22. }
  23. }

修改store

reducer.js

  1. export default ((state=defaultState,action)=>{
  2. // reducer处理,只能接收state,不能改变state
  3. if(action.type==='change_input_value'){
  4. let newState=JSON.parse(JSON.stringify(state))
  5. newState.inputValue = action.value
  6. // reducer处理完业务逻辑返回给store
  7. return newState
  8. }
  9. return state
  10. })

组件.js

  1. constructor(props){
  2. super(props)
  3. this.state=store.getState()
  4. //订阅Redux的状态,括号内为订阅之后执行的
  5. // 只有执行了该函数,state的值在组件中才会改变
  6. store.subscribe(()=>{this.setState(store.getState())})
  7. }
  8. changeInput(e){
  9. const action={
  10. type:'change_input_value',
  11. value:e.target.value
  12. }
  13. //store只是一个仓库,它并没有管理能力,它会把接收到的action自动转发给Reducer
  14. //action通过dispatch()方法传递给store
  15. store.dispatch(action)
  16. }

配置redux devTools

  1. // 创建数据存储仓库,store/index.js
  2. const store=createStore(reducer,
  3. window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())

image.png

技巧:

actionType独立出来

  • actionType单独建立一个文件:

    1. export const CHANGE_INPUT='change_input_value'
    2. export const ADD_ITEM='add_value'
    3. export const DEL_ITEM='del'
  • 导入并使用

    1. import {CHANGE_INPUT,ADD_ITEM,DEL_ITEM} from '../store/actionTypes'
    2. add(){
    3. const action={
    4. type:ADD_ITEM
    5. }
    6. store.dispatch(action)
    7. }

    Redux Action和业务逻辑分离

  • 新建store目录下的actionCreator.js ```javascript import {CHANGE_INPUT,ADD_ITEM,DEL_ITEM} from ‘../store/actionTypes’

export const changeCreateAction=(value)=>({ type:CHANGE_INPUT, value }) export const addCreateAction=()=>({ type:ADD_ITEM }) export const delCreateAction=(value)=>({ type:DEL_ITEM, value })

  1. - 导入并调用
  2. ```javascript
  3. import {changeCreateAction,addCreateAction,delCreateAction} from '../store/actionCreators'
  4. changeInput(e){
  5. const action=changeCreateAction(e.target.value)
  6. // 将action传递给store
  7. store.dispatch(action)
  8. }

原则:

  1. store是唯一的,不能同时存在多个store
  2. 只有store能改变自己的内容,reducer不能改变:store拿到了Reducer的数据,自己对自己进行了更新。
  3. Reducer必须是纯函数:调用参数相同,返回相同

组件UI和业务逻辑拆分:

  1. ui和逻辑分离
  2. 逻辑通过props属性传递到ui组件里

无状态组件:

有render方法并且没有state和业务逻辑的组件,可以提升性能

  1. import React from 'react';
  2. import 'antd/dist/antd.css'
  3. import { Input , Button , List } from 'antd'
  4. const TodoListUI=(props)=>{
  5. return(
  6. <div>
  7. <div>
  8. <Input value={props.inputValue} onChange={props.changeInput} placeholder={props.inputValue} style={{width:250,marginRight:10}}/>
  9. <Button type="primary" onClick={props.add}>增加</Button>
  10. </div>
  11. <List bordered dataSource={props.listData}
  12. renderItem={(dataItem,index)=>(
  13. <List.Item onClick={()=>{props.delItem(index)}}>{dataItem}</List.Item>
  14. )}/>
  15. </div>
  16. )
  17. }
  18. export default TodoListUI

从后端接口调取数据和redux结合

  • 配置后端(egg.js)接口 ```javascript /* @type Egg.EggPlugin / module.exports = { cors:{ enable:true, package:’egg-cors’ } }; //config.default.js config.security={ domainWhiteList: [ ‘http://localhost:3000‘ ] } //controller const Controller = require(‘egg’).Controller;

class HomeController extends Controller { async index() { const { ctx } = this; ctx.body = ‘hi, egg’; } async getListData(){ const {ctx}=this ctx.body=[ “事项1”, “事项2”, “事项3”, “事项4”, ] } async addListData(){

} async delListData(){

} }

module.exports = HomeController; //路由 module.exports = app => { const { router, controller } = app; router.get(‘/‘, controller.home.index); router.get(‘/getListData’, controller.home.getListData); };

  1. - 前端
  2. ```javascript
  3. //reducer.js
  4. import { CHANGE_INPUT,ADD_ITEM,DEL_ITEM,GET_LIST} from "./actionType";
  5. const defaultState={
  6. inputValue:''
  7. }
  8. export default ((state=defaultState,action)=>{
  9. let newState=JSON.parse(JSON.stringify(state))
  10. // reducer接收到action后进行业务逻辑处理
  11. if(action.type===CHANGE_INPUT){
  12. newState.inputValue=action.value
  13. return newState
  14. }else if(action.type===ADD_ITEM){
  15. newState.listData.push(state.inputValue)
  16. return newState
  17. }else if(action.type===DEL_ITEM){
  18. newState.listData.splice(action.value,1)
  19. return newState
  20. }else if(action.type===GET_LIST){
  21. newState.listData=action.value
  22. return newState
  23. }
  24. // reducer把数据返回给store
  25. return state
  26. })
  27. //==============todoList.jsx====================================
  28. componentDidMount(){
  29. axios.get('http://127.0.0.1:7001/getListData').then(res=>{
  30. const action=getListCreate(res.data)
  31. store.dispatch(action)
  32. })
  33. }

redux中间件:

redux-thunk

image.png

  • 在Dispatch一个Action之后,到达reducer之前,进行一些额外的操作
  • 在实际工作中你可以使用中间件来进行日志记录、创建崩溃报告,调用异步接口或者路由
  • 步骤:

    • 安装:npm install —save redux-thunk
    • 在store/index中导入 import thunk from 'redux-thunk'
    • 配置:

      • 引入applyMiddleware使用中间件import { createStore,applyMiddleware,compose} from "redux";
      • 添加增强函数(相当于链式调用)
        1. const composeEnhancer=window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__?
        2. window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}):compose
        3. // 增强函数==链式函数【可以同时使用redux dev tools和中间件】
        4. const enhancer=composeEnhancer(applyMiddleware(thunk))
        5. //创建store
        6. const store=createStore(reducer,enhancer)
    • 使用:

      • 在actionCreators.js中编写业务逻辑,此时action可以是一个函数 ```javascript import axios from ‘axios’

export const getTodoList = () =>{ return (dispatch)=>{ axios.get(‘https://www.easy-mock.com/mock/5cfcce489dc7c36bd6da2c99/xiaojiejie/getList').then((res)=>{ const data = res.data // 返回一个对象类型的action const action = getListCreate(listData) // 自动传到store中 dispatch(action) }) } } }) } } //=======

//组件.js先引入getTodoList import {getTodoList , changeInputAction , addItemAction ,deleteItemAction,getListAction} from ‘./store/actionCreatores’ componentDidMount(){ // 返回函数的action const action = getTodoList() store.dispatch(action) }

```

react-redux[暂空]:react作者封装的一个react专用的redux库