首页 > 移动平台 > 详细

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

时间:2017-01-20 23:41:29      阅读:712      评论:0      收藏:0      [点我收藏+]

前言:前面做了一下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

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!