React-Native实战二(清理app缓存+Redux )

来源:互联网 发布:传奇霸业龙脉升级数据 编辑:程序博客网 时间:2024/05/21 11:01

前言:前面做了一下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 的 storeimport  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:有需要资料的可以加群私聊我哈,不谢!!)

0 0
原创粉丝点击