react这么热门的框架也不介绍了,redux是一个单项数据流的小框架,当然不只配合react,它起初是为react而配的,现在面向所有了,比如ng-redux的项目。redux做为react的标准搭配,大有超越flux的势头。今天show一个例子来入门redux。源码在此。 (本文默认你已有react基础,es6基础)

这个效果很简单就是一个count计数,+++++的按钮按一下就会+1;input里面写什么,submit就会alert什么内容,这个demo很杂乱,是我修改的官方counter的例子,加了一些实验的东西,比较适合熟悉redux这个东西。

大家都知道,react是由一个个组件构成的,每个组件都是与其他没有关系的,数据的传递都是通过props。redux实现的单项数据流就是为react量身定做的。它维护了一个store,处理一些东西,业务逻辑,数据都在这个store里面,就把它看成一个操作数据的显示数据的东西,这个东西把它当作props传入react组件,然后就可以用来显示和操作数据了。这个react组件和平常写的react组件差不多,但是里面的处理数据是用store,也就是传入的props处理。详细的教程请戳redux中文api

有兴趣的同学可以看一下我的另一篇博文:redux源码赏析

1.首先看一下主页的html,很简单,没什么东西。里面这个ul其实没啥用的,哈哈哈。其实就是一个div,里面的东西都让react处理。引入一个bundle.js(webpack压缩后的文件)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>react+redux</title>
</head>
<body>
<div id="root">
<ul>
<li>l1</li>
<li>l2</li>
<li>l3</li>
<li>l4</li>
<li>l5</li> </ul>
</div>
<script type="text/javascript" src="bundle.js"></script>
</body>
</html>

2.主要就是main.js里的代码

import {render} from "react-dom"
import React from "react"
import {Provider} from "react-redux"
import configureStore from "./store/configureStore"
import App from './containers/app.js'
const store =configureStore(); render((
<Provider store={store}>
<App />
</Provider>
),document.getElementById('root'));

我们看它做了什么。引入了render,React,Provider,和自己写的配置store-configureStore,还有经过redux处理过的组件App。render只是es6里的写法,也可以换成平常react的写法,就不列出了。Provider也不用管,只知道redux就是这么写组件就可以了,里面把通过自己创建的store传入到react组件,然后把处理过的App组件扔在那里,就完了。主要我们看它的store怎么创建的,和App怎么处理的。

3.先看store怎么处理的。这里是/store/configureStore.js

import {applyMiddleware,createStore} from "redux";
import thunk from "redux-thunk";
import reducer from "../reducers/reducer.js" const createStoreWithMiddleware=applyMiddleware(thunk)(createStore) export default function configuerStore(initialStore){
const store=createStoreWithMiddleware(reducer,initialStore);
return store;
}

它引入了中间件thunk,具体的作用就是让action可以通过函数的处理,这个中间件只有几行。如果action是函数就执行它,交给下一个中间件,没有了就继续流程

export default function thunkMiddleware({ dispatch, getState }) {
return next => action =>
typeof action === 'function' ? // action 居然是函数而不是 plain object?
action(dispatch, getState) : //在中间件里消化掉,让该函数控制 dispatch 时机
next(action); //否则调用 next 让其他中间件处理其他类型的 action
}

接下来,可以看到创建store的函数createStoreWithMiddleware(reducer,initialStore);传入的reducer和initialStore,initialStore是初始的Store状态,可以随便取结构,比如本例的store只有一个count字段,用来存储count数字。reducer是重要的一点,它是执行业务逻辑的地方,它是一个纯函数,任何时候结果都是不变的(传入相同的东西)。

4.reducer /reducers/reducer.js"

import {combineReducers} from "redux"
import { ADD,RED } from '../actions/action'
function counter(state=0,action){
switch(action.type){
case ADD: return state+1;
case RED:return state-1;
default:return state;
}
}
const rootReducer=combineReducers({
counter
})
export default rootReducer;

combineReducers也不用管,他是组合多个reducer的,用于拆分业务。action只是描述了有事情发生了这一事实,并没有指明应用如何更新 state。而这正是 reducer 要做的事情。 reducer就是如何改变数据的一个东西,这个counter的函数就是一个reducer,它是通过看action的type的值来操作state的,如果action的type是ADD,state就+1,是RED就-1;要谨记 reducer 一定要保持纯净。只要传入参数一样,返回必须一样。没有特殊情况、没有副作用,没有 API 请求、没有修改参数,单纯执行计算。这个action又是什么?

5.action actions/action.js

export const ADD="ADD"
export const RED="RED" export function increment(){
return {
type:ADD
}
}
export function decrement(){
return {
type:RED
}
}
export function ince(){
return (dispatch,getState) =>{
//const {counter}=getState()
dispatch(increment());
}
}
export function dece(){
return (dispatch,getState)=>{
//const {counter}=getState()
dispatch(decrement())
}
}

为了简单,我把官网例子的action改了,就留下加减两个action。它是什么呢?你如何改变数据就看它了,它定义的ADD,RED两个常量,作为type,redux规定action必须有type属性,别的它不管。redux提供的api只有几个,其中有dispatch和getState,dispatch是唯一改变state的api,getState是得到当前state,所以dispatch(action)就是改变当前state的方法,我们想增加count,就是dispatch(increment());我们把它封装成ince()传递到组件里,让它可以直接改变state,也就是每次点击+++++就执行一下ince()这样就可以了。这里的ince()和dece()只是手动套了一层dispatch,其实在项目中带有副作用的操作是在这里执行,而不是在reducer里面执行,包括执行异步 API 请求,它可以不纯净。为什么它返回一个函数而上面的action返回一个对象都能够运行呢,就是因为上面的thunk middleware的作用了。

总结一下,这就是整个store了,它创建了一个store,传入了reducer(怎么根据action数据),reducer里包含了action(改变什么数据,具体怎么改)。把这个store传入组件App,就能通过props里面的方法改变count了。

6.经过redux修饰的组件

看main.js里面直接把封装的App展现出来了,我们看它怎么处理的App  /containers/app.js

import {bindActionCreators} from "redux"
import {connect} from "react-redux"
import App from '../component/App.js'
import *as Actions from '../actions/action'
function mapStateToprops(state){
return {
counter:state.counter
}
}
function mapDispatchToProps(dispatch){
return bindActionCreators(Actions,dispatch)
}
export default connect(mapStateToprops,mapDispatchToProps)(App)

bindActionCreators,看一下它的源码,它把所有的Action都封装了。 bindActionCreator把action装上一层dispatch。

//将 actionCreator 跟 dispatch 绑定在一起
let bindActionCreator => (actionCreator, dispatch) {
return (...args) => dispatch(actionCreator(...args));
} function bindActionCreators(actionCreators, dispatch) {
if (typeof actionCreators === 'function') { //如果是单个 actionCreator,绑定一词
return bindActionCreator(actionCreators, dispatch);
}
//返回一个改造过的「函数组合」
return mapValues(actionCreators, actionCreator =>
bindActionCreator(actionCreator, dispatch)
)
}

惟一使用 bindActionCreators 的场景是当你需要把 action creator 往下传到一个组件上,却不想让这个组件觉察到 Redux 的存在,而且不希望把 Redux store 或dispatch传给它。

这里的App组件就是普通react组件,修饰它的方法就是connect。我们看connect干了什么。

connect传入两个函数为参,第一个参数的名字mapStateToprops,也很清楚了,你需要把state里的什么放到props里,这里就只有counter一个字段。第二个mapDispatchToProps,把dispatch传入到props,让组件可以调用dispatch来改变数据的结构,然而有bindActionCreators,就不用dispatch了,而且我们还在action里封装的ince(),里面就是dispatch增加的action,也不用dispatch了。

把数据,怎么修改数据传到props里,然后就可以用了。

最后看一下App这个组件,怎么用数据和怎么修改数据呢?

7.APP /component/App.js

import {render} from "react-dom"
import React from "react"
class App extends React.Component {
constructor(props){
super(props);
this.handleClick=this.handleClick.bind(this);
this.onSubmit=this.onSubmit.bind(this);
}
handleClick(){
const {ince,dece,counter} = this.props;
ince();
}
onSubmit(event){
alert(this.refs.text.value);
}
render() {
const {ince,dece,counter} = this.props;
return(
<form onSubmit={this.onSubmit}>
<input ref='text' type="text" />
<div>{counter}</div><input type="button" onClick={this.handleClick} value="++++++++++" />
<button>submit</button>
</form>
)
}
}
class Bpp extends React.Component{
render(){
return (
<div>{this.props.fuk}
</div>)
}
}
class Cpp extends React.Component{
render(){
const {ince,dece,increment,decrement,counter} =this.props;
const id=this.props.params.id
return (
<div>this is cpp id为{id}</div>)
}
}
export default App;

Bpp和Cpp没有显示出来,只是用作实验,删掉也没事。(我只是忘记删了)

这里写组件是用es6的写法写的。es6封装了原生js的prototype操作,然而它是个不完全的语法糖,因为在里面不能写属性,public property也不行。

引入了React,render相当于ReactDOM.render。组件用extends关键字继承React.Componet,其实还可以用React.createClass,其实是一样的。后者还是有很多react开发者使用的,因为它比较方便,为啥说比较方便,后面再提。

看一下这个jsx,就是一个form表单,提交触发submit事件,一个输入框,一个+++++的按钮,一个div里面是{counter},这样显示数据。

值得一提的是const {ince,dece,counter} = this.props;把props传的东西拿出来。拿出来什么呢?数据和如何修改数据的东西。这里只拿出了ince和dece,他们是我们封装的action,在里面dispatch了,你就直接用它操作数据就可以了。counter是我们的数据,在div里{counter}就显示了。

onSubmit={this.onSubmit},submit执行自身定义的事件,弹出this.refs.text的值,也就是input的值。

还有注意的就是constructor里面的东西了,这个东西是在class继承的时候执行的,super(props);是必有的,如果不写也会自动给你加上,就是执行一遍父类的constructor。要注意的是

this.handleClick=this.handleClick.bind(this);
this.onSubmit=this.onSubmit.bind(this);

这两个必须要绑定一下this,不然在这两个函数里取不到this,这很坑的,而且还很麻烦。再加上es6的class功能并不完善,有的地方替代不了js的原型操作,这也就促成了很开发者用React.createClass写,组件生命周期事件还可以直接用,自然是比较方便的。

总结,这就是整个例子的代码了,

这里手绘了一幅图,主程序分为创建store和修饰app两部分,主程序main.js将他们弄到一块就完成了react-redux的例子。里面用的一些api没有详细讲解,详情看上面给出的redux中文api的链接。

webpack里面没有用任何复杂的工具,仅仅是用babel转换了一下es6,其他就没有什么了。

初入react-redux (基于webpack babel的react应用框架)的更多相关文章

  1. 重温 Webpack, Babel 和 React

    开始之前 在书写文章之前,我假设大家已经有了 JavaScript,Node 包管理工具,Linux 终端操作 这些基本技能,接下来,我将一步一步指引大家从头搭建一个 React 项目 最终实现的效果 ...

  2. react 后台(一) react + redux + react-route + webpack+ axios + antd + less

    create-react-app 项目名称(项目失败,ant 的样式出不来) 项目技术栈 react + redux + react-route + webpack+ axios + less + a ...

  3. webpack+babel+ES6+react环境搭建

    webpack+babel+ES6+react环境搭建 步骤: 1 创建项目结构 注意: 先创建一个项目目录  react  这个名字自定义,然后进入到这个目录下面 mkdir app //创建app ...

  4. react 后台(一)react + redux + react-route + webpack+ axios + antd+styled-components(替代less)

    create-react-app my-admin 项目技术栈 react + redux + react-route + webpack+ axios + antd+styled-component ...

  5. [React] react+redux+router+webpack+antd环境搭建一版

    好久之前搭建的一个react执行环境,受历史影响是webpack3.10.0和webpack-dev-server2.7.1的环境,新项目准备用webpack4重新弄弄了,旧的记录就合并发布了(在没有 ...

  6. react案例->新闻移动客户端--(react+redux+es6+webpack+es6的spa应用)

    今天分享一个react应用,应在第一篇作品中说要做一个react+redux+xxx的应用.已经做完一部分,拿出来分享.github地址为:点我就可以咯~ 这里实现了一个新闻移动站的spa.本来想写p ...

  7. 基于 Webpack 4 和 React hooks 搭建项目

    面对日新月异的前端,我表示快学不动了

  8. 基于webpack搭建的vue+element-ui框架

    花了1天多的时间, 终于把这个框架搭建起来了. 好了, 不多说了, 直接进入主题了.前提是安装了nodejs,至于怎么安装, 网上都有教程. 这里就不多说了, 这边使用的IDE是idea.1.在E:/ ...

  9. webpack+react+redux+es6开发模式

    一.预备知识 node, npm, react, redux, es6, webpack 二.学习资源 ECMAScript 6入门 React和Redux的连接react-redux Redux 入 ...

随机推荐

  1. redis4.X

    tar -zxvf ****cd /redismakecd /srcmake install vi redis.confdaemonize yes mkdir /usr/local/redis/bin ...

  2. [转帖]漫画趣解Linux内核

    漫画趣解Linux内核 https://blog.csdn.net/juS3Ve/article/details/84207142 Linux 内核漫画 今天,我来为大家解读一幅来自 TurnOff. ...

  3. Android——MaterialDesign之一Toolbar

    Toolbar 由于ActionBar设计原因只能存在活动的顶部,从而不能实现MaterialDesign的效果,现在推荐使用Toolbar,继承Actionbar,但是比起它更加的灵活. 设置主题: ...

  4. Java-Spring-获取Request,Response对象

    转载自:https://www.cnblogs.com/bjlhx/p/6639542.html 第一种.参数 @RequestMapping("/test") @Response ...

  5. SLAs-笔记

    类型 sla status determined at time intervals over a timeline: average transaction response time errors ...

  6. 学习 Spring (十五) Advisor

    Spring入门篇 学习笔记 advisor 就像一个小的自包含的方面,只有一个 advice 切面自身通过一个 bean 表示,并且必须实现某个 advice 接口,同时 advisor 也可以很好 ...

  7. UNIX口令破解机

    在编写我们的UNIX口令破解机时,我们需要使用UNIX 计算口令hash 的crypt()算法.Python 标准库中已自带有crypt 库.要计算一个加密的UNIX 口令hash,只需调用函数cry ...

  8. fpm 打包教程

    常用yum命令: Yum安装时需要安装到指定的文件夹,则需要 --installroot yum install --installroot=/usr/src/ vim 常用rpm命令: 常用yum仓 ...

  9. BZOJ3894文理分科——最小割

    题目描述  文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠 结过)  小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行 描述,每个格子代表一个同学的座位.每位同学必须从 ...

  10. 听大佬学长RQY报告有感

    听了RQY大佬的报告,我深有感触…… 数学基础很重要.首先我们要学好数学,众所周知信息学奥赛的实质是做数学题.如果你的编程能力再高,绞尽脑汁就是不会解数学题那有什么用呢?如果你会解数学题,那么你可以根 ...