初入react-redux (基于webpack babel的react应用框架)
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应用框架)的更多相关文章
- 重温 Webpack, Babel 和 React
开始之前 在书写文章之前,我假设大家已经有了 JavaScript,Node 包管理工具,Linux 终端操作 这些基本技能,接下来,我将一步一步指引大家从头搭建一个 React 项目 最终实现的效果 ...
- react 后台(一) react + redux + react-route + webpack+ axios + antd + less
create-react-app 项目名称(项目失败,ant 的样式出不来) 项目技术栈 react + redux + react-route + webpack+ axios + less + a ...
- webpack+babel+ES6+react环境搭建
webpack+babel+ES6+react环境搭建 步骤: 1 创建项目结构 注意: 先创建一个项目目录 react 这个名字自定义,然后进入到这个目录下面 mkdir app //创建app ...
- 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 ...
- [React] react+redux+router+webpack+antd环境搭建一版
好久之前搭建的一个react执行环境,受历史影响是webpack3.10.0和webpack-dev-server2.7.1的环境,新项目准备用webpack4重新弄弄了,旧的记录就合并发布了(在没有 ...
- react案例->新闻移动客户端--(react+redux+es6+webpack+es6的spa应用)
今天分享一个react应用,应在第一篇作品中说要做一个react+redux+xxx的应用.已经做完一部分,拿出来分享.github地址为:点我就可以咯~ 这里实现了一个新闻移动站的spa.本来想写p ...
- 基于 Webpack 4 和 React hooks 搭建项目
面对日新月异的前端,我表示快学不动了
- 基于webpack搭建的vue+element-ui框架
花了1天多的时间, 终于把这个框架搭建起来了. 好了, 不多说了, 直接进入主题了.前提是安装了nodejs,至于怎么安装, 网上都有教程. 这里就不多说了, 这边使用的IDE是idea.1.在E:/ ...
- webpack+react+redux+es6开发模式
一.预备知识 node, npm, react, redux, es6, webpack 二.学习资源 ECMAScript 6入门 React和Redux的连接react-redux Redux 入 ...
随机推荐
- redis4.X
tar -zxvf ****cd /redismakecd /srcmake install vi redis.confdaemonize yes mkdir /usr/local/redis/bin ...
- [转帖]漫画趣解Linux内核
漫画趣解Linux内核 https://blog.csdn.net/juS3Ve/article/details/84207142 Linux 内核漫画 今天,我来为大家解读一幅来自 TurnOff. ...
- Android——MaterialDesign之一Toolbar
Toolbar 由于ActionBar设计原因只能存在活动的顶部,从而不能实现MaterialDesign的效果,现在推荐使用Toolbar,继承Actionbar,但是比起它更加的灵活. 设置主题: ...
- Java-Spring-获取Request,Response对象
转载自:https://www.cnblogs.com/bjlhx/p/6639542.html 第一种.参数 @RequestMapping("/test") @Response ...
- SLAs-笔记
类型 sla status determined at time intervals over a timeline: average transaction response time errors ...
- 学习 Spring (十五) Advisor
Spring入门篇 学习笔记 advisor 就像一个小的自包含的方面,只有一个 advice 切面自身通过一个 bean 表示,并且必须实现某个 advice 接口,同时 advisor 也可以很好 ...
- UNIX口令破解机
在编写我们的UNIX口令破解机时,我们需要使用UNIX 计算口令hash 的crypt()算法.Python 标准库中已自带有crypt 库.要计算一个加密的UNIX 口令hash,只需调用函数cry ...
- fpm 打包教程
常用yum命令: Yum安装时需要安装到指定的文件夹,则需要 --installroot yum install --installroot=/usr/src/ vim 常用rpm命令: 常用yum仓 ...
- BZOJ3894文理分科——最小割
题目描述 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠 结过) 小P所在的班级要进行文理分科.他的班级可以用一个n*m的矩阵进行 描述,每个格子代表一个同学的座位.每位同学必须从 ...
- 听大佬学长RQY报告有感
听了RQY大佬的报告,我深有感触…… 数学基础很重要.首先我们要学好数学,众所周知信息学奥赛的实质是做数学题.如果你的编程能力再高,绞尽脑汁就是不会解数学题那有什么用呢?如果你会解数学题,那么你可以根 ...