redux的使用流程

redux

React只是DOM的一个抽象层

Web应用是一个状态机,视图与状态是一一对应的

所有的状态,保存在一个对象里面(唯一数据源)

需要使用redux的项目

  • 用户的使用方式复杂
  • 不同身份的用户有不同的使用方式(比如普通用户和管理员)
  • 多个用户之间可以协作
  • 与服务器大量交互,或者使用了WebSocket
  • View要从多个来源获取数据

从组件层面考虑,什么样子的需要redux:

  • 某个组件的状态,需要共享
  • 某个状态需要在任何地方都可以拿到
  • 一个组件需要改变全局状态
  • 一个组件需要改变另一个组件的状态
redux有四个组成部分

store:用来存储数据

reducer:真正的来管理数据

actionCreators:创建action,交由reducer处理

view:用来使用数据

redux的流程

1)store通过reducer创建了初始状态
2)view通过store.getState()获取到了store中保存的state挂载在了自己的状态上
3)用户产生了操作,调用了actions 的方法
4)actions的方法被调用,创建了带有标示性信息的action
5)actions内部通过调用store.dispatch方法将标志性的action发送到了reducer中
6)reducer接收到action并根据标识信息判断之后返回了新的state
7)store的state被reducer更改为新state的时候,store.subscribe方法里的回调函数会执行,此时就可以通知view去重新获取state

例如创建如下案例
在文本框输入文字后,按下回车键,添加到列表中

store通过reducer创建了初始状态,在reducer中定义一个数组

store/index.js

import {createStore} from 'redux';
import reducer from './reducer';
const store  = createStore(reducer)
export default store

store/reducer.js

let state = {
    list: [
        { id: 1, title: "星期一", isFinished: true },
        { id: 2, title: "星期二", isFinished: false }
    ]
}
const reducer = (prevState = state, action) => {
    //让上一条数据默认为state
    let newState = { ...prevState }
    return newState
}

view通过store.getState()获取到了store中保存的state挂载在了自己的状态上

在TodoContent组件中展示数据

import React, { Component } from 'react'
import store from '../store'
import TodoInput from './TodoInput'
export default class Redux extends Component {
    constructor() {
        super()
        this.state = {
            list: []
        }
    }
    setList = () => {
        //从store的getState()方法中获取到list并更改state中的list数据
        this.setState({
            // Store对象包含所有数据。如果想得到某个时点的数据,就要对 Store 生成快照。当前时刻的 State,可以通过store.getState()拿到。
            list: store.getState().list
        })
    }
    componentDidMount() {
        this.setList()
        //Store 允许使用store.subscribe方法设置监听函数,一旦 State 发生变化,就自动执行这个函数。当state的数据改变时,就去执行setList,由此state的数据也会改变,render也会重新渲染
        store.subscribe(() => {
            this.setList()
        })
    }
    handleCheck = (id) => {
        actions.changeList(id)
    }
    remove = (id) => {
        actions.removeList(id)
    }
    render() {
        let { list } = this.state
        return (
            <div>
                <TodoInput />
                {
                    list.map(item => {
                        return <li key={item.id} style={{textDecoration:item.isFinished ? 'line-through':'none'}}><input type="checkbox" checked={item.isFinished} onChange={this.handleCheck.bind(this, item.id)}  /> {item.title}
                            <button onClick={this.remove.bind(this, item.id)}>删除</button>
                        </li>
                    })
                }
            </div>
        )
    }
}

当input框输入文本时,按下键盘下的Enter,列表会增加一条

也就是当用户产生了操作,调用了actions 的方法

组件TodoInput

import actionCreators from "../../store/actionCreators"
export default class TodoInput extends Component {
    handleKey=e=>{
        if(e.keyCode==13){
            // 当按下Enter键时,触发actionCreators下的addNewTode
            actionCreators.addList(e.target.value)
            e.target.value=""
        }
      
    }
    render() {
        return (
            <input placeholder="请输入内容" onKeyUp={this.handleKey}/>
        )
    }
}

actions的方法被调用,创建了带有标示性信息的action
actions内部通过调用store.dispatch方法将标志性的action发送到了reducer中

actionCreators.js

const actionCreators = {
    addList(title){
        //需要定义一个具有特殊标识的action对象
        let action = {
            type:"addList",
            title
        }
        //需要将action对象派发给reducer
        store.dispatch(action)
    },
 changeList(id) {
        let action = {
            type: "changeList",
            id
        }
        store.dispatch(action)
    },
    removeList(id) {
        let action = {
            type: "removeList",
            id
        }
        store.dispatch(action)
    },
}
export default actions

reducer接收到action并根据标识信息判断之后返回了新的state,store.subscribe方法里的回调函数会执行,此时就可以通知view去重新获取state

reducer.js

let state = {
    list: [
        { id: 1, title: "星期一", isFinished: true },
        { id: 2, title: "星期二", isFinished: false }
    ]
}
const reducer = (prevState = state, action) => {
    let newState = { ...prevState }
    switch (action.type) {
        case "addList":
            newState.list.push({
                id: handleList.getId(newState.list),
                title: action.title
            })
            break;
        case "changeList":
            newState.list = handleList.changeList(newState.list, action.id)
            break;
        case "removeList":
            newState.list = handleList.removeList(newState.list, action.id)
            break;
        default:
            break;
    }
    return newState
}
const handleList = {
    getId(list) {
        list = list.slice()
        if (list.length === 0) return 1
        return list.sort((a, b) => {
            return b.id - a.id
        })[0].id + 1
    },
    changeList(list, id) {
        list = list.slice()
        for (let i = 0; i < list.length; i++) {
            if (list[i].id === id) {
                list[i].isFinished = !list[i].isFinished
            }
        }
        return list
    },
    removeList(list, id) {
        list = list.slice()
        return list.filter((item) => {
            console.log(item)
            if (item.id === id) {
                return false
            }
            return true
        })

    }

}
export default reducer
posted @ 2020-09-07 21:30  Cupid05  阅读(538)  评论(0编辑  收藏  举报