zoukankan      html  css  js  c++  java
  • 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
    
    请用今天的努力,让明天没有遗憾。
  • 相关阅读:
    img标签为什么可以设置宽高
    高度和宽度的操作
    自增自减运算符
    读取标签内容:innerHTML和innerText的区别 text()和html()的区别
    js中的常用方法
    js中style,currentStyle和getComputedStyle的区别以及获取css操作方法(考虑兼容性和局限性)
    IE盒模型与W3C盒模型区别
    css四种定位方式及其区别
    css隐藏元素的方法何区别
    Hibernate之HQL
  • 原文地址:https://www.cnblogs.com/cupid10/p/13629368.html
Copyright © 2011-2022 走看看