前言:前面做了一下rn的清理app缓存功能,下面把前面说的rn中处理页面与页面之间的数据传递问题解决一下,在解决之前,我们先来认识一下什么是redux。
先附上redux的官方demo地址:https://github.com/alinz/example-react-native-redux#counter-example
1、什么是redux?
redux是一个用于管理js应用状态的容器。redux出现时间并不是很长,在它出现之前也有类似功能的模块出现,诸如flux等等。redux设计的理念很简单,似乎最初这个开发团队就有让redux可以方便融入在server, browser, mobile client端的打算。目前在github上redux-*的第三方中间件、插件越来越多。如果react项目中想使用redux,那么就有react-redux插件来完成配合。
2、为什么要用redux?
搞过React Native的都知道,rn中更新组件主要通过改变state从而更新组件。
先盗用一张网络上的rn生命周期图:
当我们改变state的时候,rn会重新走一遍render方法,从而更新组件,但是在rn中,每个页面都管理者自己的state,如果需要一个页面管理另外一个页面的state,那么我们就有点无从下手了,但是redux很巧妙的帮我们管理着所有的state。
redux提供了一套机制来组织管理整个应用状态。
Redux有三部分组成:store,action,reducer。
store:维护全局的state,以及将action和reducer结合起来。
action:用来传递state的信息。(比如:我们在action中处理登陆操作,将返回的user对象传递给对应的reducer.)
reducer:reducer是简单的处理函数,通过传入旧的state和指示操作的action来更新state,从而达到页面的刷新。
上图是redux状态改变的流程。action -> reducer -> 新store -> 反馈到UI上有所改变。
直白一点就是:用户发送点击清理缓存按钮(action)
—>
reducer接受到用户发送的action,并且接收到action中携带了(缓存大小、是否清理完毕等信息)
—>
reducer返回一个新的state(是否清理成功)
—>
state返回到全局变量store中
—>
回调用户页面方法,重新走render方法—>更新页面的值。
下面结合我们前面的清理缓存的例子来集成下redux:
首先安装相关库(进入项目的根目录执行下面命令):
安装redux: npm install –save redux
安装redux绑定库: npm install –save React-redux
安装开发者工具: npm install –save-dev redux-devtools
安装异步action构造器: npm install –save redux-thunk
包都很小,想必大家很快就实现了!!
第一步:创建store
///创建redux 的 store
import reducers from ‘../Redux/reducers‘;
import { Provider } from ‘react-redux‘;
import { createStore, applyMiddleware} from ‘redux‘;
import thunk from ‘redux-thunk‘;//引入异步操作
const middlewares = [thunk];
const createSoreWithMiddleware = applyMiddleware(...middlewares)(createStore);
class Main extends Component {
// 构造
constructor(props) {
super(props);
// 初始状态
this.state = {
store:createSoreWithMiddleware(reducers)
};
}
render() {
//创建store
return (
<Provider store={this.state.store}>
<Main2/>
</Provider>
);
};
}
module.exports = Main;
以上是我的app主入口,Main2是我们的app主页面,也就是前面的那张截图。
我们需要把所有的reducer加载到store中,reducer就是用来处理返回给用户state的东西,
一般会创建一下index.js文件来统一管理所有的reduce文件:
import clear from ‘./clear‘;
import {combineReducers} from ‘redux‘
let MainReducers = combineReducers({
clear
})
module.exports = MainReducers;
我们需要建一个叫clear的reducer文件:
import * as types from ‘../actions/actionTypes‘;
const initialState = {
size: ‘0.00M‘
};
export default function clear(state = initialState, action = {}) {
switch (action.type) {
case types.CLEAR_CACHE:
return {
...state,
size:action.size
};
default:
return state;
}
}
因为获取缓存大小都在action中处理了,然后我们直接返回state为action中的size。
对应的action:
import * as types from ‘./actionTypes‘;
var CacheManager = require(‘react-native-http-cache‘);
export function clearCache() {
return dispatch=> {
let result = CacheManager.getCacheSize().then((value)=> {
dispatch({type: types.CLEAR_CACHE, size: Math.round((value / 1024 / 1024) * 100) / 100 + ‘M‘});
}, (erro)=> {
dispatch({type: types.CLEAR_CACHE, size: ‘0M‘});
});
}
}
这里说一下dispatch,说dispatch之前,先说一下store对象中的一些方法:
dispatch用来发送一个action,getstate用来获取state,subscribe用来注册回调函数。
我们在action中用到了dispatch来返回我们的操作:
return dispatch=> {
let result = CacheManager.getCacheSize().then((value)=> {
dispatch({type: types.CLEAR_CACHE, size: Math.round((value / 1024 / 1024) * 100) / 100 + ‘M‘});
}, (erro)=> {
dispatch({type: types.CLEAR_CACHE, size: ‘0M‘});
});
因为getCacheSize获取值是异步的操作,所以我们不能直接返回一个action对象,我们通过拿到value 后又发送一个action(并且把获取到的value封装进action)的方法发送给store,然后给reducer,最后返回给用户界面。
第二步:关联页面跟store
在我们的Main2(主页面中建立与store的关联关系)
/**
* 主体框架类
*/
import React, { Component } from ‘react‘;
import {
AppRegistry,
StyleSheet,
Text,
View,
Image,
Platform,
Navigator,
StatusBar
} from ‘react-native‘;
/**
* 导入外部组件类
*/
import TabNavigator from ‘react-native-tab-navigator‘;
var Home = require(‘../Home/YQYHome‘);
var Mine = require(‘../Mine/YQYMine‘);
var More = require(‘../More/YQYMore‘);
var Store = require(‘../Store/YQYStore‘);
var ScreenUtils = require(‘../ScreenUtils‘);
let colors = [‘11‘, ‘22‘];
//连接各个组件
import {bindActionCreators} from ‘redux‘;
import * as counterActions from ‘../Redux/actions/counterActions‘;
import { connect } from ‘react-redux‘;
var MiXin = require(‘react-timer-mixin‘);
class Main2 extends Component {
// 构造
constructor(props) {
super(props);
// 初始状态
this.state = {
selectedTab: ‘home‘//默认第一个home页
};
}
render() {
console.log(‘renderMain2‘);
return (
<TabNavigator>
{/*--首页--*/}
{this._renderItem(‘首页‘, ‘icon_tabbar_homepage‘, ‘icon_tabbar_homepage_selected‘, ‘home‘, Home)}
{/*--商家--*/}
{this._renderItem(‘商家‘, ‘icon_tabbar_merchant_normal‘, ‘icon_tabbar_merchant_selected‘, ‘shop‘, Store)}
{/*--我的--*/}
{this._renderItem(‘我的‘, ‘icon_tabbar_mine‘, ‘icon_tabbar_mine_selected‘, ‘mine‘, Mine)}
{/*--更多--*/}
{this._renderItem(‘更多‘, ‘icon_tabbar_misc‘, ‘icon_tabbar_misc_selected‘, ‘more‘, More)}
</TabNavigator>
);
}
/**
* 渲染item
* @param title
* @param iconUri
* @param selectedIconUri
* @param selectedTab
* @param component
* @returns {XML}
* @private
*/
_renderItem(title, iconUri, selectedIconUri, selectedTab, component, badge) {
let self = this;
const { state, actions } = self.props;
return (
<TabNavigator.Item
title={title}
renderIcon={() => <Image source={{uri:iconUri}} style={styles.iconStyle} resizeMode=‘stretch‘/>}
renderSelectedIcon={() => <Image source={{uri:selectedIconUri}} style={styles.iconStyle} resizeMode=‘stretch‘/> }
onPress={()=>{
this.setState({
selectedTab:selectedTab
});
if(selectedTab===‘more‘&&actions.clearCache){
MiXin.setTimeout(()=>{
actions.clearCache();
},500);
}
}}
selected={this.state.selectedTab===selectedTab}
badgeText={badge}
selectedTitleStyle={styles.selectedTitleStyle}
titleStyle={{
fontSize:ScreenUtils.setSpText(10),
color:‘#333333‘
}}
tabStyle={{
alignItems:‘center‘,
marginBottom:6
}}
>
<Navigator
initialRoute={{name:title,component:component}}
configureScene={()=>{
return Navigator.SceneConfigs.PushFromRight
}}
renderScene={(route,navigator)=>{
let Component=route.component;
return (
<View style={{flex:1}}>
<StatusBar
translucent={true}
barStyle={‘light-content‘}
backgroundColor=‘transparent‘
>
</StatusBar>
<Component
{...actions}
size={state.size}
navigator={navigator}
/>
</View>
)
}}
/>
</TabNavigator.Item>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: ‘center‘,
alignItems: ‘center‘,
backgroundColor: ‘#F5FCFF‘,
},
welcome: {
fontSize: 20,
textAlign: ‘center‘,
margin: 10,
},
instructions: {
textAlign: ‘center‘,
color: ‘#333333‘,
marginBottom: ScreenUtils.scaleSize2(5),
},
iconStyle: {
width: ScreenUtils.scaleSize2(40),
height: ScreenUtils.scaleSize2(40),
},
selectedTitleStyle: {
color: ‘orange‘
}
});
//关联当前页面与store,通过props的方式传给组件
export default connect(state => ({
state: state.clear
}),
(dispatch) => ({
actions: bindActionCreators(counterActions, dispatch)
})
)(Main2);
此时页面中的props拥有store中特定的state跟actions,于是我们可以很容易的发送一个action跟获取发送action之后 ruducer返回给我的state:
render() {
console.log(‘renderMore‘);
let{size,clearCache}=this.props;
{/*---清空缓存----*/}
<CommCell
title=‘清空缓存‘
onItemClick={()=>{
this._clearCache();
}
}
desc={size}
/>
}
用过TabNavigator的童鞋都知道,当我们第一次进入app的时候加载了四个view,以后就不会加载了,但是我们需要当点击more页面的时候,每次都要重新获取一下缓存的大小,所以我们要在我们放在主页面的TabNavigator做下处理了,当点击的item为more的时候,发送一个action最后更新more中的内容。。
<TabNavigator.Item
title={title}
renderIcon={() => <Image source={{uri:iconUri}} style={styles.iconStyle} resizeMode=‘stretch‘/>}
renderSelectedIcon={() => <Image source={{uri:selectedIconUri}} style={styles.iconStyle} resizeMode=‘stretch‘/> }
onPress={()=>{
this.setState({
selectedTab:selectedTab
});
if(selectedTab===‘more‘&&actions.clearCache){
MiXin.setTimeout(()=>{
actions.clearCache();
},500);
}
}}
我们可以看到,有了redux,我们很容易的管理了所有的state,从而达到了通信的目的。但是redux的作者也不建议大家在不满足redux的条件下使用redux。
从组件角度看,如果你的应用有以下场景,可以考虑使用 Redux。
某个组件的状态,需要共享
某个状态需要在任何地方都可以拿到
一个组件需要改变全局状态
一个组件需要改变另一个组件的状态
当然,主要是我是结合我的项目讲的,可能理解起来比较吃力哈,
大家也可以看一下阮大神的博客:
http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_one_basic_usages.html
最后祝大家早日成为大神哈!!!!一起努力,(ps:有需要资料的可以加群私聊我哈,不谢!!)
React-Native实战二(清理app缓存+Redux )
原文:http://blog.csdn.net/vv_bug/article/details/54632365