微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

React Native-14.React Native 常用API及实践 AsyncStorage

AsyncStorage简介

AsyncStorage,我们完全可以理解它为iOS中的NSUserDefalut。

它有很多方法,每一个方法都有回调函数,第一个参数是错误对象,错了就是展示错误信息,否则为null。都会返回一个Promise对象。

  • static getItem(key:string,callback:(error,result)): 根据键来获取值,获取的结果会在回调函数中。
  • static setItem(key:string,value:string,callback:(error)): 设置键值对。
  • static removeItem(key:string,callback:(error)): 将根据键移出一项
  • static mergeItem:(key:string,callback:(error)): 合并现有的值和输入值。
  • static clear(callback:(error)): 清除所有的项目。
  • static getAllKeys(callback:(error)): 获取所有的键。
  • static multiGet(keys,callback:(errors,result)):获取多项,其中keys是字符串数组。
  • static multiSet(keyvaluePairs,callback:(errors)):设置多项,其中keyvaluePairs是字符串的二维数组。
  • static multiRemove(keys,callback(errors)):删除多项,其中keys是字符串数组。
  • static multiMerge(keyvaluePairs,callback:(errors)):多个键值合并,其中keyvaluePairs是字符串中的二维数组。

没图说个xx

我们来做个demo,具体使用以下。

效果

代码

'use strict';
var React = require('react-native');
var Dimensions = require('Dimensions');
var {
  AppRegistry,StyleSheet,Text,View,Image,ScrollView,WebView,NavigatorIOS,AsyncStorage,TouchableOpacity,} = React;


var Model = [
    {
        id: '1',title:'商品1',desc:'哎哟~不错哦',price: 10000,url:'http://ww4.sinaimg.cn/thumb180/4d7f0a6dgw1f18crfemfog20b405mqv7.gif'
    },{
        id: '2',title:'商品2',desc:'哎哟~不错哦2',price: 10330,url:'http://ww3.sinaimg.cn/thumb180/6aa09e8fgw1f18abnz36mg20b30697wj.gif'
    },{
        id: '3',title:'商品3',desc:'哎哟~不错3',price: 100003,url:'http://ww4.sinaimg.cn/thumb180/6298156bgw1f18ydrmj4cj20hi0bhq5r.jpg'
    },{
        id: '4',title:'商品4',desc:'哎哟~不错哦4',price: 100004,url:'http://ww1.sinaimg.cn/thumb180/a5d15efdgw1f18k8pu0cyj20jg0jbdja.jpg'
    },{
        id: '5',title:'商品5',desc:'哎哟~不错哦5',price: 100005,url:'http://ww2.sinaimg.cn/thumb180/005yYQOngw1f18lqh7hx9j326r1gincv.jpg'
    },{
        id: '6',title:'商品6',desc:'哎哟~不错哦6',price: 100006,url:'http://ww2.sinaimg.cn/thumb180/5ba8d1cbgw1f18hhiaj3jj21kw1kw10x.jpg'
    }
];

var styles = StyleSheet.create({
    container : {
        flex: 1
    },row : {
        flexDirection: 'row',marginBottom: 10,},item : {
        flex: 1,marginLeft:5,borderWidth: 1,borderColor: '#ddd',marginRight: 5,height: 100,img: {
        flex: 1,backgroundColor: 'transparent',item_text: {
        backgroundColor: '#000',opacity:0.7,color:'#fff',height:25,lineHeight:18,textAlign:'center',marginTop:74
    },btn: {
        backgroundColor: '#ff7200',height: 33,textAlign : 'center',color: '#fff',marginLeft:10,marginRight: 10,lineHeight: 24,marginTop: 40,fontSize: 18,list_item : {
        marginLeft: 5,padding:5,height: 30,borderRadius: 3,list_item_desc : {
        flex: 2,fontSize: 15,list_item_price: {
        flex: 1,textAlign: 'right',clear: {
        marginTop : 10,backgroundColor: '#fff',color: '#000',borderWidth:1,marginLeft: 10,marginRight:10,height:33,textAlign: 'center',}

});

//列表项组件
var Item = React.createClass({
    render:function(){
        return(
            <View style = {styles.item}>
                <TouchableOpacity onPress = {this.props.press}>
                    <Image
                        resizeMode = 'contain'
                        style = {styles.img}
                        source = {{uri:this.props.url}}>
                        <Text numberLines = {1} style = {styles.item_text}>
                            {this.props.title}
                        </Text>
                    </Image>
                </TouchableOpacity>
            </View>
            );
    }
});

//列表组件
var List = React.createClass({
    getinitialState: function(){
        return{
            count: 0
            };
    },componentDidMount: function() {
        var _that = this;
        AsyncStorage.getAllKeys(function(err,keys){
            if (err) {
                //Todo:存储取数据出错 ,给用户提示错误信息。
            }
            //将存储的商品条数反应到按钮上
            _that.setState({
                count:keys.length
            });
        });
    },render: function(){
        var list = [];
        for(var i in Model){
            if (i % 2 ===0) {
                var row = (
                    <View style = {styles.row} key = {i}>
                        <Item url={Model[i].url}
                        title = {Model[i].title}
                        press = {this.press.bind(this,Model[i])}></Item>

                        <Item url = {Model[parseInt(i) + 1].url}
                        title = {Model[parseInt(i) + 1].title}
                        press = {this.press.bind(this,Model[parseInt(i) + 1])}></Item>
                    </View>
                );
                list.push(row);
            }
        }

        var counts = this.state.count;
        var str = null;

        if (counts) {
            str = ',共'+counts+'件商品';
        }

        return(
            <ScrollView style = {{marginTop:10}}>
                {list}
                <Text onPress = {this.goGouWu} style = {styles.btn}>
                    去结算{str}
                </Text>
            </ScrollView>
        );
    },//前往购物车方法
    goGouWu: function(){
        this.props.navigator.push({
            component:GouWu,title: '购物车'
        });
    },//商品被选中方法
    press: function(data){
        var count = this.state.count;
        count++;
        //改变数字状态
        this.setState({
            count: count
        });
        //AsyncStorage 存储
        AsyncStorage.setItem('SP-'+this.genId() + '-SP',JSON.stringify(data),function(err){
            if (err) {
                //Todo:存储出错
            }
        });
    },genId: function(){
        return 'xxxxxxx-xxxx-2xxxx-bxxxxxxxxx'.replace(/[xy]/g,function(c){
            var r = Math.random() * 16|0,v = c == 'x'?r:(r & 0x3 | 0x8);
            return v.toString(16);
        }).toupperCase();
    }
});

var GouWu = React.createClass({
    getinitialState:function(){
        return{
            data:[],price:0
        };
    },render:function(){
        var data = this.state.data;
        var price = this.state.price;
        var list = [];
        for(var i in data){
            price += parseFloat(data[i].price);
            list.push(
                <View style = {[styles.row,styles.list_item]} key = {i}>
                    <Text style = {styles.list_item_desc} >
                        {data[i].title}
                        {data[i].desc}
                    </Text>
                    <Text style = {styles.list_item_price} >${data[i].price}</Text>
                </View>
            );
        }


        var str = null;
        if (price) {
            str = ',共'+ price.toFixed(1)+'元'
        }

        return(
            <ScrollView style = {{marginTop:10}}>
                {list}
                <Text style = {styles.btn} onPress = {this.paySuccess}>支付{str}</Text>
                <Text style = {styles.clear} onPress = {this.clearStorage}>清空购物车</Text>
            </ScrollView>
        )
    },keys){
            if (err) {
                //Todo:存储取数据出错
                //如果发生错误,这里直接返回(return)防止进入下面的逻辑
            }

            AsyncStorage.multiGet(keys,function(errs,result){
                //Todo:错误处理
                //得到的结果是二维数组
                //result[i][0]表示我们存储的键,result[i][1]表示我们存储的值
                var arr = [];
                for(var i in result){
                    arr.push(JSON.parse(result[i][1]));
                }
                _that.setState({
                    data:arr
                });
            });

        })
    },clearStorage:function(){
        var _that = this;
        AsyncStorage.clear(function(err){
            if (!err) {
                _that.setState({
                    data:[],price:0,});
                alert('购物车已经清空')
            }
            //Todo:err
        });
    },paySuccess: function(){
        var _that = this;
        AsyncStorage.clear(function(err){
            if (!err) {

                alert("支付成功!")

                _that.props.navigator.pop();


            }
            //Todo:err
        });

        _that.setState({
                    data:[],count:0,str:'去结算'
                });
    }

});
var wxsPrj = React.createClass({
  render: function() {
    return (
        <NavigatorIOS style = {styles.container}
                      initialRoute = {
                        {
                            component:List,title:'商品列表',}
                      }/>

    );
    }
});

AppRegistry.registerComponent('wxsPrj',() => wxsPrj);

代码详解

列表组件代码详解

这次代码比较长,功能多一点点。
首先我们来看一下模块, 我们创建Model(数据源) styles(样式列表) Item(列表项组件) List(列表组件) GouWu(购物车组件)
前三个没有什么好说的,先来说一下List组件:
在List组件中,我们用Model数据源来渲染列表项。使用i%2 ==0 来控制,每两个列表项目在一行中。
在press方法中我们让count+1,并且使用AsynStorage.setItem将选中的商品数据添加到App本地存储中。这里之所以使用SP-为前缀,-SP为后缀,采用GUID为存储的键名的一部分,是为了区分其他数据,好处:

  • 可以缺粉用户数据,例如username信息。
  • 可以放置key重复,保证同名商品都能被添加进购物车。

这样我们就把商品信息存储起来了。

我们在componentDidMount方法中作了一个处理,在用户第二次进入的时候,如果没有支付,依旧会告诉用户购物车中的商品数。使用Asy ncStorage.getAllKeys获取数据的条数,

在去结算按钮中,我们注册了点击方法goGouWu事件。使用this.props.navigator.push将购物车组件加载。

购物车组件代码详解

我们在购物车组件中使用AsyncStorage.getAllKeys 来获取 AsyncStorage中的Key,然后再使用AsyncStorage.multiGet 获取商品数据的数组。我们将获取的数据设置到this.state.data上,这样当组件被加载完成后,就会显示商品列表。

我们在结算和清空按钮上的操作函数中使用了AsyncStorage.clear清除AsyncStorage中的所有数据。

遗留问题

我们支付成功后,或者清空购物车后回到商品列表界面,发现还在提示我们购物车中有商品。这里大家有方法的,贴评论吧。刷新前一个页面的数据。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如果组件之中有复用的代码,需要重新创建一个父类,父类中存储公共代码,返回子类,同时把公用属性...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例如我们的 setState 函数式同步执行的,我们的事件处理直接绑定在了 dom 元素上,这些都跟 re...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使用,可能是不了解。我公司的项目就没有使用,但是在很多三方库中都有使用。本小节我们来学习下如果使用该...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接触 react 就一直使用 mobx 库,上手简单不复杂。
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc 端可以使用分页进行渲染数限制,在移动端可以使用下拉加载更多。但是对于大量的列表渲染,特别像有实时数据...
本小节开始前,我们先答复下一个同学的问题。上一小节发布后,有小伙伴后台来信问到:‘小编你只讲了类组件中怎么使用 ref,那在函数式组件中怎么使用呢?’。确实我们...
上一小节我们了解了固定高度的滚动列表实现,因为是固定高度所以容器总高度和每个元素的 size、offset 很容易得到,这种场景也适合我们常见的大部分场景,例如...
上一小节我们处理了 setState 的批量更新机制,但是我们有两个遗漏点,一个是源码中的 setState 可以传入函数,同时 setState 可以传入第二...
我们知道 react 进行页面渲染或者刷新的时候,会从根节点到子节点全部执行一遍,即使子组件中没有状态的改变,也会执行。这就造成了性能不必要的浪费。之前我们了解...