一、什么是flux

  1.redux的设计思想与flux是差不多一样的,所以我们先来了解什么flux

  2.flux是一种设计模式或者说是框架。以mvc模式来划分的话react是mvc中的view, flux相当于mc,m就是model c就是control。那么我们就明白flux到底是什么了,看下图:

  flux包含四个部分 Store、Dispatch、Action、View,其中Store就对应着model,Dispatch、Action就组合成了Control。这么划分仅仅是帮助全局理解flux到底是什么。

  3.flux就是一种设计模式,当view或者用户产生一个Action时,Dispatch会解析Action根据不同的Action修改Store,被修改的Store会发消息通知View说:我已经修改了过来取我并更新你自己吧。

  4.一个简单例子

// store
var Store = {
state:{
loginData:{
type:'login',
data:'no login',
},
logoutData:{
type:'logout',
data:'',
}
},
login:function(data){
this.state.loginData = data;
},
logout:function(data){
this.state.logoutData = data;
},
getState:function(){
return this.state;
},
sendEvent:function(){
this.callback();
},
addChangeListener: function(callback) {
this.callback = callback;
},
removeChangeListener: function(callback) {
}
} // Dispatch
var Dispatcher = require('flux').Dispatcher;
var dispatch = new Dispatcher();
dispatch.register(function(payload){
switch (payload.type){
case 'login' :
Store.login(payload);
Store.sendEvent();
break;
case 'logout':
Store.logout(payload);
Store.sendEvent();
break;
}
}); // View
Store.addChangeListener(()=>{
console.log('{\nloginData:{type:'+Store.getState().loginData.type + ' data:' + Store.getState().loginData.data+ '}');
console.log('logoutData:{type:'+Store.getState().logoutData.type + ' data:' + Store.getState().logoutData.data+ '}\n}');
}); // Action
var loginAction = {
type: 'login',
data: 'login sucessed'
};
var logoutAction = {
type: 'logout',
data: 'logout sucessed'
};
console.log('登录....');
dispatch.dispatch(loginAction);
console.log('退出....');
dispatch.dispatch(logoutAction);

二、redux

  1.我们先看看看官网的一个例子

var Redux = require('redux')
var createStore = Redux.createStore function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}
// 创建store
let store = createStore(counter)
store.subscribe(() =>
console.log(store.getState())
) store.dispatch({ type: 'INCREMENT' })
//
store.dispatch({ type: 'INCREMENT' })
//
store.dispatch({ type: 'DECREMENT' })
//

  可以看到redux与flux原理是一样的,只是实现不一样。

  1.redux把dispatch封装到了Store里

// 所以我们可以直接通过store来发送dispatch
store.dispatch({ type: 'INCREMENT' })

  2.抽象出一个reducer概念(counter就是一个reducer),reducer就是一个[根据不同的dispatch处理并生产新的state的一个程序]。

// 处理自增、或者自减的程序
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT':
return state + 1
case 'DECREMENT':
return state - 1
default:
return state
}
}

  要理解redux,其实就是要理解Redux提供的Store与reducer。 

三、react中使用redux

  我们将会重头创建一个React-native项目,然后加入redux框架 

#初始化一个react-native项目
$ react-native init reduxTest
$ cd reduxTest/ios
$ open reduxTest.xcodeproj
#这样就创建并打开了一个iOS的react-native项目

  1.添加app.js

import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
TouchableHighlight
} from 'react-native';
class App extends Component {
onPress(){ }
render() {
let welcome = this.props.appInfo?this.props.appInfo.welcome:'Welcome to Redux test!'
return (
<View style={styles.container}>
<Text style={styles.welcome}>
{welcome}
</Text>
<TouchableHighlight onPress={this.onPress.bind(this)}>
<Text >
Click me!
</Text>
</TouchableHighlight>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
});
module.exports = App;

  2.修改reduxTest/index.ios.js

import React, { Component } from 'react';
import {
AppRegistry,
} from 'react-native';
import App from './app'
export default class reduxTest extends Component {
render() {
return (
<App></App>
);
}
}
AppRegistry.registerComponent('reduxTest', () => reduxTest);

  这时候我们得到一个简单的测试app,下面我通过redux来管理app组件的state(redux把state映射到props)。

  效果:当点击Click me! 按钮时,会吧welcome信息改为 have clicked!

  具体流程就是:

  (1).点击 Click me! 按钮 ,会通过redux的Store发送一个dispatch给reducer,reducer把welcome改为‘have clicked’

  (2).然后redux会通知app 组件重新渲染

  3.安装redux、react-redux、redux-thunk

$ npm install redux --save
$ npm install react-redux --save
$ npm install redux-thunk --save

  3.直接上源码,代码后面有解释

  总共涉及4个文件,需要重点关注的代码将会被标红。

  • index.ios.js --  创建store 
  • app.js      --  根据store的改变做出相应的处理、用户点击时发出action
  • reducer.js    --  处理action
  • action.js      --  具体的action

  index.ios.js:

import React, { Component } from 'react';
import {
AppRegistry,
} from 'react-native'; import App from './app'
import appReducer from './reducer' import {createStore,
applyMiddleware} from 'redux';
import {Provider} from 'react-redux';
import thunk from 'redux-thunk'; let store = createStore(appReducer,
applyMiddleware(thunk) // 用于异步的action
); export default class reduxTest extends Component {
render() {
return (
<Provider store={store}>
<App></App>
</Provider> );
}
}
AppRegistry.registerComponent('reduxTest', () => reduxTest);

  解析

  这里引入了四个redux相关组件

  • createStore        --- 是一个函数,用于创建store
  • applyMiddleware    --- 是一个函数,用于使用中间件
  • hunk                     --- 是一个函数,是中间件用于使action函数支持异步;
  • Provider                --- 是一个react组件,主要提供一个全局的store使得它的子组件都能访问到

  创建store的代码:

let store = createStore(
appReducer,
applyMiddleware(thunk) // 用于异步的action
);
/**
@appReducer :是一个reducer,我们说过是用于处理action的。
@applyMiddleware(thunk) : 应用一个叫thunk的中间件,任何一个action执行前会先执行thunk 这里我们应该记住:
store提供一个保存state的地方
store也提供了一个发出dispatch的方法
store也提供了一个监听state的方法
*/

  Provider:Provider是提供者,意思就是给他的子组件提供一个store,这个store就是我们上面创建的。

  app.js:

import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
TouchableHighlight
} from 'react-native';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux'; import WelcomeAction from './action' class App extends Component {
// 定义 上线文里store属性的类型为object
static contextTypes = {
store: React.PropTypes.object
}
componentDidMount() {
// store的作用1: 监听state的变化
const { store } = this.context;
store.subscribe(
()=>{
// store的作用2: 获取state
let state = store.getState();
// state改变了
console.log('state:',state);
}
);
}
onPress(){
// 1.直接用store发生dipatch
let action = {
type:'welcome',
data:{
text:'have clicked from app.js',
}
}
// store的作用3: 发送dispatch
this.context.store.dispatch(action) // this.props.onPressAction()
}
render() {
let welcome = this.props.welcome
return (
<View style={styles.container}>
<Text style={styles.welcome}>
{welcome}
</Text>
<TouchableHighlight onPress={this.onPress.bind(this)}>
<Text >
Click me!
</Text>
</TouchableHighlight>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
});
function mapStateToProps(state) {
return {
welcome: state.welcome
}
}
function mapDispatchToProps(dispatch) {
return {
onPressAction:bindActionCreators(WelcomeAction,dispatch),
}
}
module.exports = connect(mapStateToProps,mapDispatchToProps)(App);

  解析

 (1)获取store

  因为app组件是Provider组件的子组件,所以app组件跟Provider组件是共享一个context(上下文)的 --- 这个是react的规定,不了解的请自行补相应知识。

  只要在app组件定义一下store的类型就能使用了

// 定义 上线文里store属性的类型为object
static contextTypes = {
store: React.PropTypes.object
}
// 通过下面就能获取到store
this.context.store

  这个store是与创建Provider时传入的store是同一个

<Provider store={store}>
<App></App>
</Provider>

 (2)使用store

  获取到store之后我们就可以用于发送dispatch、监听state了

  发送dispatch:

    let action = {
type:'welcome',
data:{
text:'have clicked from app.js',
}
}
// store的作用3: 发送dispatch
this.context.store.dispatch(action)

   action参数是一个对象,对象结构没有做要求。

  action被dispatch之后会被reducer处理,处理完后就会发一个通知说state已经更新了。

  通过下面代码来监听通知

// store的作用1: 监听state的变化
const { store } = this.context;
store.subscribe(
()=>{
// store的作用2: 获取state
let state = store.getState();
// state改变了
// 根据state做相应的渲染
console.log('state:',state);
}
);

 我看下面的reducer是怎么处理action的

 reducer.js:

function Reducer(state = {welcome:'Welcome to Redux test!'}, action) {
switch (action.type) {
case 'welcome':
return {welcome:action.data.text};
default:
return state
}
}
module.exports = Reducer;

  解析:

  很简单的处理,如果action的type等于‘welcome’的话,就直接返回一个对象{welcome:action.data.text};

  监听者收到的就是这个返回的对象。

  值得注意,Reducer的参数 state = {welcome:'Welcome to Redux test!'},是state的默认值

---------------------------------------------------------------------

  每次都通过this.context.sotre来dispatch、subscribe,大家都觉得很烦,好吧redux已经做了封装:

  引入两个组件:

  • connect   ----  用于封装App组件
  • bindActionCreators   --- 绑定action的构造者

  具体使用:

function mapStateToProps(state) {
return {
welcome: state.welcome
}
}
function mapDispatchToProps(dispatch) {
return {
onPressAction:bindActionCreators(WelcomeAction,dispatch),
}
} module.exports = connect(mapStateToProps,mapDispatchToProps)(App);

  解析:

  function mapStateToProps(state)

  正如函数名所表示,它的作用就是把state映射到props上。这里的state是指store保存的state,props是指app组件的props。

  这个函数需要返回一个对象

return {
welcome: state.welcome
}

  然后通过connect组件封装一下

module.exports = connect(mapStateToProps,mapDispatchToProps)(App);

  这样子,在app组件内部就能通过this.props.welcome来获取store保存的state对应的welcome的值了,是不是分方便?

  既然state能映射到props,那么dispatch action也能映射


import WelcomeAction from './action'
function mapDispatchToProps(dispatch) {
return {
onPressAction:bindActionCreators(WelcomeAction,dispatch),
}
}
module.exports = connect(mapStateToProps,mapDispatchToProps)(App);

  上面的代码意思就是吧dispatch映射到props上,dispatch是sotre的dispatch,props是app的props.

  我们可以这样直接发出一个action,

this.props.onPressAction()

  onPressaction()等同于  WelcomeAction

  WelcomeAction是什么请看往下看:

  action.js:

function WelcomeAction () {
// 异步
return (dipatch, getState) => {
return new Promise((resolve,reject)=>{
setTimeout(()=>{
let action = {
type:'welcome',
data:{
text:'have clicked??',
}
}
dipatch(action);
resolve();
},2000);
});
}
// 同步
// return {
// type:'welcome',
// data:{
// text:'have clicked',
// }
// }
}
module.exports = WelcomeAction   

  WelcomeAction函数用到dispatch等于store.dispatch

  这样做的目的是把action独立出来方便单独管理。

  action函数,如果需要异步执行就返回一个Promise,同步执行可以直接返回一个新的state  

  值得注意如果action函数需要异步执行,在创建store的时候必须使用中间件trunk

import thunk                from 'redux-thunk';
let store = createStore(
appReducer,
applyMiddleware(thunk) // 用于异步的action
);

redux介绍与入门的更多相关文章

  1. .NET平台开源项目速览(6)FluentValidation验证组件介绍与入门(一)

    在文章:这些.NET开源项目你知道吗?让.NET开源来得更加猛烈些吧!(第二辑)中,给大家初步介绍了一下FluentValidation验证组件.那里只是概述了一下,并没有对其使用和强大功能做深入研究 ...

  2. Redux介绍及基本应用

    一.Redux介绍  Redux的设计思想很简单,就两句话: Web应用是一个状态机,神力与状态是一一对应的 所有的状态,保存在一个对象里面 二.Redux基本概念和API Store Store就是 ...

  3. freemarker语法介绍及其入门教程实例

    # freemarker语法介绍及其入门教程实例 # ## FreeMarker标签使用 #####一.FreeMarker模板文件主要有4个部分组成</br>####  1.文本,直接输 ...

  4. (转)私有代码存放仓库 BitBucket介绍及入门操作

    转自:http://blog.csdn.net/lhb_0531/article/details/8602139 私有代码存放仓库 BitBucket介绍及入门操作 分类: 研发管理2013-02-2 ...

  5. NET平台开源项目速览(6)FluentValidation验证组件介绍与入门(转载)

    原文地址:http://www.cnblogs.com/asxinyu/p/dotnet_Opensource_project_FluentValidation_1.html 阅读目录 1.基本介绍 ...

  6. 读写Word的组件DocX介绍与入门

    本文为转载内容: 文章原地址:http://www.cnblogs.com/asxinyu/archive/2013/02/22/2921861.html 开源Word读写组件DocX介绍与入门 阅读 ...

  7. [转帖]Druid介绍及入门

    Druid介绍及入门 2018-09-19 19:38:36 拿着核武器的程序员 阅读数 22552更多 分类专栏: Druid   版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议 ...

  8. Redis介绍及入门安装及使用

    Redis介绍及入门安装及使用 什么是Redis Redis is an open source (BSD licensed), in-memory data structure store, use ...

  9. Mysql数据库的简单介绍与入门

    Mysql数据库的简单介绍与入门 前言 一.下载与安装 1.下载 官网下载MYSQL5.7.21版本,链接地址https://www.mysql.com/downloads/.下载流程图如下: 找到M ...

随机推荐

  1. 一张图轻松搞懂javascript event对象的clientX,offsetX,screenX,pageX区别

    总是会被javascript的event对象的clientX,offsetX,screenX,pageX 弄得头晕,于是决定做个图来区分一下(画得我手那个酸呀....) 先总结下区别: event.c ...

  2. Coursera台大机器学习课程笔记5 -- Theory of Generalization

    本章思路: 根据之前的总结,如果M很大,那么无论假设泛化能力差的概率多小,都无法忽略,所以问题转化为证明M不大,然后上章将其转化为证明成长函数:mh(N)为多项式级别.直接证明似乎很困难,本章继续利用 ...

  3. python直接执行另一个文件中的代码

    看你弄的这么辛苦,给你的方法exec(open(".py","r").read)open(".py",'r').read() 就是读取文件的 ...

  4. Apache Commons CLI官方文档翻译 —— 快速构建命令行启动模式

    昨天通过几个小程序以及Hangout源码学习了CLI的基本使用,今天就来尝试翻译一下CLI的官方使用手册. 下面将会通过几个部分简单的介绍CLI在应用中的使用场景. 昨天已经联系过几个基本的命令行参数 ...

  5. clock()、time()、clock_gettime()和gettimeofday()函数的用法和区别【转】

    转自:http://www.cnblogs.com/krythur/archive/2013/02/25/2932647.html 转自http://blog.sina.com.cn/s/blog_7 ...

  6. windows系统nginx配置root绝对路径的问题

    看了下logs下面的error.log文件,发现路径有问题,修改了conf配置,把root的路径反斜杠要用两个反斜杠进行转义,再次运行正常了.

  7. angularJS中directive与directive 之间的通信

    上一篇讲了directive与controller之间的通信:但是我们directive与directive之间的通信呢? 当我们两个directive嵌套使用的时候怎么保证子directive不会被 ...

  8. set、def、lambda、内置函数、文件操作

    set : 无序,不重复,可以嵌套 .add (添加元素) .update(接收可迭代对象)---等于批量 添加 .diffrents()两个集合不同差 .sysmmetric difference( ...

  9. JS的兼容函数

    获取类名的兼容函数 //obj.getElementsByClassName 只能在现代浏览器中使用,不能在IE8以下使用 //两个参数 classname 类名 obj 范围 function ge ...

  10. java中filter的用法 内部资料 请勿转载 谢谢合作

    filter过滤器主要使用于前台向后台传递数据是的过滤操作.程度很简单就不说明了,直接给几个已经写好的代码: 一.使浏览器不缓存页面的过滤器 Java代码   import javax.servlet ...