redux介绍与入门

时间:2023-02-24 16:14:05

一、什么是flux

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

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

redux介绍与入门

  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. &period;NET平台开源项目速览&lpar;6&rpar;FluentValidation验证组件介绍与入门&lpar;一&rpar;

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

  2. Redux介绍及基本应用

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

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

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

  4. &lpar;转&rpar;私有代码存放仓库 BitBucket介绍及入门操作

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

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

    原文地址: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. &lbrack;转帖&rsqb;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. How to Allow MySQL Client to Connect to Remote MySql

    How to Allow MySQL Client to Connect to Remote MySQ By default, MySQL does not allow remote clients ...

  2. Intellij Idea无法从Controller跳转到视图页面的解决方案

    解决方案: 第一步,确认配置了Spring支持,如下图: 一般情况下,配置完上面就可以正常导航了,但是今天要说的不是一般情况,否则也就不说了,如果经过第一步设置后,还是不能正常导航的同学,可以接着看第 ...

  3. 可以返回执行结果的system函数加强版本

    在GNU Linux C编程中,要想进行系统命令的执行的话,只提供了system接口,但是此接口并不能得到命令执行后所输出的值,而只能够得到命令是否执行成功的结果.仅仅这样的功能还是不够的,有的时候是 ...

  4. PHP 中 const define 的区别

    在php中定义常量时,可用到const与define这两种方法,那他们到底有什么区别呢? 1.const用于类成员变量的定义,一经定义,不可修改.define不可用于类成员变量的定义,可用于全局常量. ...

  5. 记录一次安装OpenGL的漫长过程

    尝试codeblock和Dev-C++ 这学期新开了一门计算机图形图像的课,里面涉及到openGL,中午跑到图书馆开始倒腾OpenGL. 因为电脑里本来有codeblock,于是就想不用教材里面所说的 ...

  6. 如何向微软 Docs 和本地化社区提交翻译贡献

    Docs (docs.microsoft.com)是微软新版的文档网站,重新规划了各项技术栈的文档结构,看起来比 MSDN 可读性更好.虽然 Docs 提供了各种语言的版本,但大多是机器翻译,某些中文 ...

  7. Vue----目录结构

    目录结构: (1):build:---------------------------------------------------------------------------------:保存 ...

  8. 24&period;Linux-Nand Flash驱动&lpar;分析MTD层并制作NAND驱动&rpar;

    1.本节使用的nand flash型号为K9F2G08U0M,它的命令如下: 1.1我们以上图的read id(读ID)为例,它的时序图如下: 首先需要使能CE片选 1)使能CLE 2)发送0X90命 ...

  9. php登陆绑定手机验证码使用阿里大于接口

    https://doc.alidayu.com/doc2/index.htm  一条0.045 元  新注册送10块 

  10. 查看&period;net frameword版本

    官方答案. 具体步骤如下: 1.打开注册表(Win+R,输入regedit): 2.输入注册表路径:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framewor ...