Redux入门到使用。

Stella981
• 阅读 527

Redux入门到使用。 简介

Redux是针对JavaScript应用的可预测状态容器。

如果熟悉设计模式之观察者模式理解起来就简单了。就是将你在其他组件中需要用到的数据放到一个容器中,那么组件就可以从其中取放数据的东西就是redux的工作。

特性:

  • 可预测性(predictable): 因为Redux用了reducer与纯函数(pure function)的概念,每个新的state都会由旧的state建来一个全新的state。因而所有的状态修改都是”可预测的”。

  • 状态容器(state container): state是集中在单一个对象树状结构下的单一store,store即是应用程序领域(app domain)的状态集合。

  • JavaScript应用: 这说明Redux并不是单指设计给React用的,它是独立的一个函数库,可通用于各种JavaScript应用。

核心概念

action:是把数据从应用(译者注:这里之所以不叫 view 是因为这些数据有可能是服务器响应,用户输入或其它非 view 的数据 )传到 store 的有效载荷。它是 store 数据的唯一来源。一般来说你会通过 store.dispatch() 将 action 传到 store。

reducer:指定了应用状态的变化如何响应 actions,并发送到 store 的,记住 actions 只是描述了_有事情发生了_这一事实,并没有描述应用如何更新 state。

store: store就是把action和reducer联系到一起的对象,store本质上是一个状态树,保存了所有对象的状态。任何UI组件都可以直接从store访问特定对象的状态。
Store 有以下职责:

  • 维持应用的 state;

  • 提供 `getState()` 方法获取 state;

  • 提供 `dispatch(action)` 方法更新 state;

  • 通过 `subscribe(listener)` 注册监听器;

  • 通过 `subscribe(listener)` 返回的函数注销监听器。
    再次强调一下 Redux 应用只有一个单一的 store

基本原理

Redux入门到使用。

这个数据流的位于最中心的设计是一个AppDispatcher(应用发送器),你可以把它想成是个发送中心,不论来自组件何处的动作都需要经过它来发送。每个store会在AppDispatcher上注册它自己,提供一个callback(回调),当有动作(action)发生时,AppDispatcher(应用发送器)会用这个回调函数通知store。

由于每个Action(动作)只是一个单纯的对象,包含actionType(动作类型)与数据(通常称为payload),我们会另外需要Action Creator(动作创建器),它们是一些辅助函数,除了创建动作外也会把动作传给Dispatcher(发送器),也就是调用Dispatcher(发送器)中的dispatch方法。

Dispatcher(发送器)的用途就是把接收到的actionType与数据(payload),广播给所有注册的callbacks。它这个设计并非是独创的,这在设计模式中类似于pub-sub(发布-订阅)系统,Dispatcher则是类似Eventbus的概念。

基本使用

安装

npm install --save react-reduxnpm install --save-dev redux-devtools

实例
主要是理解观察者模式,以及结合原理图先理解
redux的action,reducer,store基本运作。

import { createStore } from 'redux'/** * This is a reducer, a pure function with (state, action) => state signature. * It describes how an action transforms the state into the next state. * * The shape of the state is up to you: it can be a primitive, an array, an object, * or even an Immutable.js data structure. The only important part is that you should * not mutate the state object, but return a new object if the state changes. * * In this example, we use a `switch` statement and strings, but you can use a helper that * follows a different convention (such as function maps) if it makes sense for your * project. *//** * 来源:官网:https://github.com/reduxjs/redux *  * 第一步:定义reducer */function counter(state = 0, action) {  switch (action.type) {    case 'INCREMENT':      return state + 1    case 'DECREMENT':      return state - 1    default:      return state  }}// Create a Redux store holding the state of your app.// Its API is { subscribe, dispatch, getState }.    //第二步:根据reducer规则生成storelet store = createStore(counter)// You can use subscribe() to update the UI in response to state changes.// Normally you'd use a view binding library (e.g. React Redux) rather than subscribe() directly.// However it can also be handy to persist the current state in the localStorage.    //第三步:定义数据(即state)变化之后的派发规则store.subscribe(() => console.log(store.getState()))store.subscribe(() => console.log(store.getState()))store.subscribe(() => console.log(store.getState()))// The only way to mutate the internal state is to dispatch an action.// The actions can be serialized, logged or stored and later replayed.   //第四步:触发数据变化store.dispatch({ type: 'INCREMENT' })// 1store.dispatch({ type: 'INCREMENT' })// 2store.dispatch({ type: 'DECREMENT' })// 1

常规使用

一般的文件结构,基本就是store目录下

Redux入门到使用。

文件

actions的操作
user.js:主要包含user模块下的action操作。

import * as types from '../constants/types'export function loginSuccess(data) {    return {        type: types.LOGOIN_SUCCESS,        payload: data    }}export function logOut() {    return {        type: types.LOGOUT    }}

reducers的操作
module/user.js:定义

import * as types from '../../constants/types';export function user(state = 0,action){    switch(action.type) {        case types.LOGOIN_SUCCESS:            console.log("user......"+ action.payload);            return state+10;        case types.LOGOUT:            return state - 10;        default:            return state;    }}

index.js
将所有reducers的集合在一起。

import { combineReducers } from 'redux'import { user } from './module/user'const rootReducer = combineReducers({  /* your reducers */  user})export default rootReducer

store的操作

import { createStore } from 'redux'import rootReducer from './reducers'export default function configureStore(initialState) {    const store = createStore(rootReducer,initialState,        window.devToolsExtension ? window.devToolsExtension() : undefined        )    return store}

组件中的操作(简单)

import React from 'react';import { bindActionCreators } from 'redux';import { connect } from 'react-redux';import ComA from './ComA'import ComB from './ComB'import * as userInfoActions from '../store/actions/user' class BodyIndex extends React.Component {    componentDidMount() {        this.props.userInfoActions.loginSuccess({            id:'呵呵呵呵',            username: 'bibibiibibi'        })    }    render() {        return (            <div>                <p>Hello world</p>                <ComA user={this.props.user}/>                <ComB user= {this.props.user} />            </div>        )    }}function  mapStateToProps(state) {    console.log("mapStateToProps...."+state);    return {        user: state.user.userInfo    }}function mapDispatchToProps(dispatch) {    return {        userInfoActions: bindActionCreators(userInfoActions,dispatch)    }}export default connect(    mapStateToProps,    mapDispatchToProps)(BodyIndex)

组件中的操作(常规)
使用connect 这样子可以省去mapDispatchToProps,mapDispatchToProps的操作。

import React from 'react';import { connect } from 'react-redux';import { addComment } from '../store/actions/comment'@connect(    state => ({comment:state.comments.comment}),    { addComment }   ) class TestCom extends React.Component {    componentDidMount() {      this.props.addComment({          comment: 100      })      }    render() {        console.log("render...."+this.props.comment);        return (            <div>                <p>TestCom.... {this.props.comment} </p>            </div>        )    }}export default TestCom;

总结

最后,如果对 Java、大数据感兴趣请长按二维码关注一波,我会努力带给你们价值。觉得对你哪怕有一丁点帮助的请帮忙点个赞或者转发哦。

Redux入门到使用。

本文分享自微信公众号 - 爱编码(ilovecode)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
2星期前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
00_设计模式之语言选择
设计模式之语言选择设计模式简介背景设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。设计模式(Designpattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
6个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这