转载请注明出处:王亟亟的大牛之路
这两天组里来了几个新人,有的用过redux,有的没用过,为了让他们上手或者理解的更透彻,就写了个demo,代码逻辑来源于https://github.com/ninty90/react-native-redux-demo
开篇前先安利
android:https://github.com/ddwhan0123/Useful-Open-Source-Android
react-native:https://github.com/ddwhan0123/Useful-Open-Source-React-Native
源码地址:https://github.com/ddwhan0123/ReduxDemo
演示效果:
理论知识:
http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_one_basic_usages.html
http://www.jianshu.com/p/0e42799be566
http://www.jianshu.com/p/3334467e4b32
理论知识重复炒冷饭等于制造网络垃圾,所以贴上几篇我觉得写得不错的给大家瞅瞅
核心理念:
Store:应用只有一个单一的 Store,State是这个状态集合某一时刻的状态
Action:改变state的载体,也是Store的数据源
Reducer:更新Store的具体操作者
ok,你现在肯定云里雾里的,我们用代码边写边解释
项目结构:
Action相关
MathType
@H_404_38@export @H_404_38@const ADD_TYPE = 'ADD_TYPE';
@H_404_38@export @H_404_38@const MINUS_TYPE = 'MINUS_TYPE';
这里是2个常量,”加类型”,”减类型”,我们每种action都有他相对应的类型,可以写在Action里也可以写一个类型对他进行划分,我习惯是拆的越细越好
MathAction
// action类型
import * as types from '../type/MathType';
// 每一个action方法返回一个新的"state"对象,他就是应用当前的状态
export @H_404_38@function add(intvalue) {
console.log('---> MainAction add intvalue ' + intvalue);
@H_404_38@return {
type: types.ADD_TYPE,result: intvalue,}
};
export @H_404_38@function minus(intvalue) {
console.log('---> MainAction minus intvalue ' + intvalue);
@H_404_38@return {
type: types.MINUS_TYPE,}
};
Reducer相关
MathReducer
@H_404_38@import * as @H_404_38@Type from'../type/MathType';
//初始化
const initState = {
result: 0
};
export default function mathReducer(state = initState,action = {}) {
switch (action.@H_404_38@type) {
@H_404_38@case @H_404_38@Type.ADD_TYPE:
console.@H_404_38@log('---> mathReducer action.type ' + action.@H_404_38@type);
@H_404_38@return {
...state,result: action.result + 10,};
break;
@H_404_38@case @H_404_38@Type.MINUS_TYPE:
console.@H_404_38@log('---> mathReducer action.type ' + action.@H_404_38@type);
@H_404_38@return {
...state,result: action.result - 10,};
default:
@H_404_38@return state;
}
}
肉眼看起来很简单,这里接受两种类型的action一个是➕,一个是➖,每次他都会改变传入参数的值,而且是一定改变,一定会+10或者-10!
reducer只是一个方法,传入什么,返回什么。结果是个恒定值,只要传入参数不变,返回参数一定也不变!
reducers
@H_404_38@import Mathreducer @H_404_38@from './Mathreducer';
@H_404_38@import {combineReducers} @H_404_38@from 'redux';
export default combineReducers({
mathStore: Mathreducer,});
这是一个reducer的大容器,你所有reducer丢一个方法里也不是不能处理,但是性能差加难以维护,所以redux提供combineReducers来帮你整合reducer
Store相关
store是个应用级持有的对象,所以我们把他放到了”根”页面里去做初始化,因为我们之后还会用到异步action,所以还用到redux-thunk
的相关内容
@H_404_38@import {Provider} from 'react-redux';
@H_404_38@import {createStore,applyMiddleware} from 'redux';
@H_404_38@import thunk from 'redux-thunk';
@H_404_38@import reducers from'./reducer/reducers';
const middlewares = [thunk];
const createSoreWithMiddleware = applyMiddleware(...middlewares)(createStore);
@H_404_38@import React from 'react';
@H_404_38@import Main from'./Main';
export @H_404_38@default @H_404_38@class App @H_404_38@extends React.PureComponent {
constructor(props) {
@H_404_38@super(props);
@H_404_38@this.state = {
store: createSoreWithMiddleware(reducers)
}
}
//前面一些只是对象,方法相关的操作,肉眼可以识别,Provider是让我们决定使用redux的一个原因,它可以让我们操作容器内的组件却不需要手动传递内容
//想想复杂应用来一个 4层以上的json要你你自己操作的话的工作量吧
render() {
@H_404_38@return (
<Provider store={@H_404_38@this.state.store}>
<Main/>
</Provider>
)
}
}
只需要在外面套一层,所有子控件的属性竟在掌握!
页面代码
@H_404_38@import React from'react';
@H_404_38@import {connect} from 'react-redux';
//加减的两种action
@H_404_38@import {add,minus} from './action/MathAction';
@H_404_38@import {
Text,View,TouchableHighlight,} from 'react-native';
@H_404_38@class Main @H_404_38@extends React.Component {
constructor(props) {
@H_404_38@super(props);
@H_404_38@this.addPress = @H_404_38@this.addPress.bind(@H_404_38@this);
@H_404_38@this.minusPress = @H_404_38@this.minusPress.bind(@H_404_38@this);
//初始值,也可以是外部传入
@H_404_38@this.state = {
intvalue: 100,}
}
addPress() {
console.log('---> Main addPress');
@H_404_38@this.props.dispatch(add(@H_404_38@this.state.intvalue));
}
minusPress() {
console.log('---> Main minuPress');
//dispatch(action) 方法更新 state
@H_404_38@this.props.dispatch(minus(@H_404_38@this.state.intvalue));
}
//状态变化时会被调用
shouldComponentUpdate(nextProps,nextState) {
console.log('---> Main shouldComponentUpdate');
@H_404_38@if (nextProps.result !== @H_404_38@this.props.result) {
@H_404_38@this.state.intvalue = nextProps.result;
console.log('---> Main shouldComponentUpdate this.state.intvalue ' + @H_404_38@this.state.intvalue);
@H_404_38@return @H_404_38@true;
}
}
render() {
console.log('---> Main render');
@H_404_38@return (
<View style={{justifyContent: 'center'}}>
<TouchableHighlight onPress={@H_404_38@this.addPress}>
<Text style={{fontSize: 15}}>
按我会加
</Text>
</TouchableHighlight>
<TouchableHighlight style={{marginTop: 30}} onPress={@H_404_38@this.minusPress}>
<Text style={{fontSize: 15}}>
按我会减
</Text>
</TouchableHighlight>
<Text style={{marginTop: 30,color: '#ffaa11'}}>{@H_404_38@this.state.intvalue}</Text>
</View>
)
}
}
function select(store) {
@H_404_38@return {
result: store.mathStore.result,}
}
//connect方法建立数据与状态的关系,达到刷新ui的效果
export @H_404_38@default connect(select)(Main);
这样这个简单的demo就讲完了,什么?看不懂,我也觉得 这说的是啥啊,过程都没讲清楚,ok 看下console你就明白了!
//首页被加载出来
05-19 20:52:49.094 5992-24741/? I/ReactNativeJS: ---> Main render
//页面点击了 “按我会加”
05-19 20:52:57.746 5992-24741/? I/ReactNativeJS: ---> Main addPress
//action得到了响应获取到了 100(正常的方法调用嘛?继续看!)
05-19 20:52:57.747 5992-24741/? I/ReactNativeJS: ---> MainAction add intvalue 100
//传递到了reducer获取到了触发的类型
05-19 20:52:57.747 5992-24741/? I/ReactNativeJS: ---> mathReducer action.type ADD_TYPE
//页面收到了state改变的讯息,回调被触发
05-19 20:52:57.759 5992-24741/? I/ReactNativeJS: ---> Main shouldComponentUpdate
//新的值是之前的100+reducer的10=110
05-19 20:52:57.759 5992-24741/? I/ReactNativeJS: ---> Main shouldComponentUpdate this.state.intvalue 110
//刷新数据
05-19 20:52:57.759 5992-24741/? I/ReactNativeJS: ---> Main render
//第二次操作,不解释了
05-19 20:53:02.010 5992-24741/? I/ReactNativeJS: ---> Main minuPress
05-19 20:53:02.010 5992-24741/? I/ReactNativeJS: ---> MainAction minus intvalue 110
05-19 20:53:02.010 5992-24741/? I/ReactNativeJS: ---> mathReducer action.type MINUS_TYPE
05-19 20:53:02.015 5992-24741/? I/ReactNativeJS: ---> Main shouldComponentUpdate
05-19 20:53:02.015 5992-24741/? I/ReactNativeJS: ---> Main shouldComponentUpdate this.state.intvalue 100
05-19 20:53:02.015 5992-24741/? I/ReactNativeJS: ---> Main render
action reducer本身看起来平淡无奇,但是在store内轮转使得我们省去了大量setState的人工操作,避免了各种不可描述的render().
但是 redux处理不好会各种多次render页面,之后的文章我会讲一讲异步的action和react-native优化
我是王亟亟!我们下篇见
有问题可以扫码加好友询问噢,非公众号,闲人勿扰!