Redux设计思想, React-redux实现计数器功能

当项目越来越复杂时,组件越来越多的时候,组件之间数据的共享就成为了一个问题,那么Redux就是用来解决各个组件之间数据共享的问题的。

redux在vue,node,react都可以使用

在这里插入图片描述
action:官方的解释是action是把数据从应用传到 store 的有效载荷,它是 store 数据的唯一来源;要通过本地或远程组件更改状态,需要分发一个action;
reducer:action发出了做某件事的请求,只是描述了要做某件事,并没有去改变state来更新界面,reducer就是根据action的type来处理不同的事件;
store:store就是把action和reducer联系到一起的对象,store本质上是一个状态树,保存了所有对象的状态。任何UI组件都可以直接从store访问特定对象的状态。
在Redux中,所有的数据(比如state)被保存在一个被称为store的容器中 ,在一个应用程序中只能有一个store对象。当一个store接收到一个action,它将把这个action代理给相关的reducer。reducer是一个纯函数,它可以查看之前的状态,执行一个action并且返回一个新的状态。

Redux工作流

React Components 借书的用户
Action Creators “我要借XX书”
Store 图书管理员
Reducers 借阅历史记录本

设计思想

视图和状态是一一对应的
所有的状态,都保存在一个对象里面

纯函数底层实列计数器
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button onclick="store.dispatch({type:'COUNT_DECRMENT',num:1})">-</button>
    <h1 id="count"></h1>
    <button onclick="store.dispatch({type:'COUNT_INCRMENT',num:1})">+</button>
    <!-- 点击加减首先调用store里面的dispathch的方法 -->
    <script>
        const createStrore = (reducer) => {
            //集中管理state,dispatch
            let state=null
            const getState = () => state;
            const listeners = [];
            const subscribe = (listener) => listeners.push(listener)
            const dispatch = (action) => {
                state=changeState(state, action)//运算执行
                listeners.forEach((listener) => listener())
            }
            dispatch({})
            //定义一个监听器,用于管理所有定义的方法
            return {
                getState,dispatch,subscribe
            }
        }
        const contState = {
            count: 0,
        }
        const changeState = (state,action) => {
            if(!state) return contState
            switch (action.type) {
                case "COUNT_DECRMENT":
                    return {
                        count:state.count - action.num,
                    }
                case "COUNT_INCRMENT":
                return {
                        count:state.count + action.num,
                    }
                default: 
                return state
            }
        }
        const store = createStrore(changeState)//初始进来执行store里面的
        const render = () => {
            document.getElementById('count').innerHTML = store.getState().count
        }
        render()//初始化渲染contState下的count
        store.subscribe(render)//类似更新数据
    </script>
</body>
</html>

在 react 中使用 redux

react-redux提供两个核心的api
Provider:提供store,根据单一store的原则,一般只出现在顶层

connect:用于连接展示组件和React store

Redux 不支持多个 store。相反,只有一个单一的store和一个根级的reduce函数(reducer)。随着应用不断变大,你应该把根级的reducer拆成多个小的 reducers,分别独立地操作state树的不同部分,而不是添加新的stores。这就像一个 React 应用只有一个根级的组件,这个根组件又由很多小组件构成。

不同的业务模块有自己的reducers,使用 combineReducers 方法将所有的reducer整合到一起。

react-redux 实现一个简单的计数器功能

安装依赖:在终端中执行下面的命令,安装 redux 和 react-redux
yarn add redux react-redux -S

store.js文件

import {createStore} from 'redux'
//解构出redux中的createStore方法
/**
 * reducer是形式为(state,action)=>state 的纯函数
 * 在reducer中对state设置默认值
 * reducer的作用是通过判断action传过来的值,对数据进行操作
 * 当state变化后,需要返回一个新的state,而不是修改传入的参数
**/
import  reducer from'./reducer'
const store=createStore(reducer)
export default store;

reducer.js
reducer 最终返回一个新的state,当 state 被更改后,store.subscribe 方法里的回调函数就会执行,会通知 view 去重新获取 state,做视图的更新;

const defaultState={
    count:1
}

const reducer=(state=defaultState,action)=>{
    switch(action.type){
        case 'inc':
            return {
                count:state.count+action.num
            }
        case 'dec':
            return {
                count:state.count-action.num
            }
        default:
            return state;
    }
}
export default reducer;

connect.js

//帮我们把redux和展示组件做关联,将store里的属性和方法挂载到组件里
//格式为connect(mapStateToProps, mapDispatchToProps)
// 将第一个参数中返回的属性转化为展示组件props上的属性;
// 将第二个参数中返回的方法转化为展示组件props上的方法;
// 如果只想获取到方法,在第一个参数传null;

import {connect} from 'react-redux'
const mapState=(state)=>{
    return {
        count:state.count
    }
}

const mapDispatch=(dispatch)=>{
    return {
        increm:(data)=>{
            dispatch({type:'inc',num:2})
        },
        increm:()=>{
            dispatch({type:'inc',num:2})
        }
    }
}
connect(mapState,mapDispatch)

Count.jsx

import React, { Component } from 'react'
import Button from './Button' 
import connect from './connect'
 class Count extends Component {
    render() {
        return (
            <div>
                <Button type='inc'>+</Button>
                <span>{this.props.count}</span>
                <Button type='dec'>-</Button>
            </div>
        )
    }
}
export default connect(Count)
//使用 connect 对当前组件做一个增强,Count 组件里就可以通过 this.props 读取到 store 中的数据;

Button.jsx
// 使用 connect 对当前组件做一个增强,Button 组件里通过 this.props 调用 connect 中的方法;
// connect 中调用 store.dispatch 方法将 action 发送到 reducer 中;
// reducer 接收到 action,对数据进行处理后,返回新的 state;
// 当 state 被更新的时候,store.subscribe 方法会执行,通知 view 去重新获取 state;
// 获取到新的 state 后,会触发 render() 重新渲染页面;

import React, { Component } from 'react'
import connect from './connect'
class Button extends Component {
    handleClick = () => {
        console.log(this.props)
        let {type,incre,decrem}=this.props
        if(type==='inc') incre(2)
        else decrem()
    }
    render() {
        return (
            <button onClick={this.handleClick}>
                {this.props.children}
            </button>
        )
    }
}
export default connect(Button)

index.js

import Count from './15-redux/呆猫/Count'
//自己定义的文件名所处位置,
import  {Provider} from 'react-redux'
//引入store挂载
import store from './15-redux/呆猫/store'
ReactDOM.render(
  <Provider store={store}>
  <Count/>
  </Provider>
 ,
  document.getElementById('root')
);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值