React Native之轻量级存储AsyncStorage

AsyncStorage是一个简单的、异步的、持久化的以键值对形式进行数据存储的存储系统,对于App来说是全局性的。它的作用等价于iOS的NSUserDefaluts或Android的SharedPreferences,使用AsyncStorage用来替换老旧的LocalStorage。

方法

它有很多方法,每一个方法都有回调函数,第一个参数是错误对象,错了就是展示错误信息,否则为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 , value: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是字符串中的二维数组。

示例

简单存储:

setData(text){  
  AsyncStorage.setItem(AsyncStorageKey,text,()=>{  
    this.setState({  
      data:text,  
    });  
  });  
}

注意:可以设置一个回调,设置成功后,调用回调,修改状态机变量。

删除指定的KEY值

delData(){  
  // 读取key字段并将结果作为第二个参数传递给callback。  如果有任何错误发生,则会传递一个Error对象作为第一个参数。返回一个Promise对象。  
  AsyncStorage.getItem(AsyncStorageKey,(error,text)=>{  
    if(text=== null ){  
      alert(AsyncStorageKey +"没有对应的值");  
    }else{  
      //删除数据  
      AsyncStorage.removeItem(AsyncStorageKey,()=>{  
        this.setState({  
          data:"",  
        },()=>{  
          alert('删除成功');  
        });  
      });  
    }  
  });  
}

完整代码:

import React, { Component } from 'react';
import {
  StyleSheet,
  View,
  Text,
  TouchableHighlight,
  Dimensions,
  AsyncStorage
} from 'react-native';

const {width, height} = Dimensions.get('window');


var data = "";
const AsyncStorageKey = "AS_";
export default class AsyncStorageExample extends Component {

  constructor(props) {
    super(props);
    this.state = {
      data:""
    };
  }

  setData(text){
    AsyncStorage.setItem(AsyncStorageKey,text,()=>{
      this.setState({
        data:text,
      });
    });
  }

  delData(){
    // 读取key字段并将结果作为第二个参数传递给callback。
    // 如果有任何错误发生,则会传递一个Error对象作为第一个参数。返回一个Promise对象。
    AsyncStorage.getItem(AsyncStorageKey,(error,text)=>{
      if(text=== null ){
        alert(AsyncStorageKey +"没有对应的值");
      }else{
        //删除数据
        AsyncStorage.removeItem(AsyncStorageKey,()=>{
          this.setState({
            data:"",
          },()=>{
            alert('删除成功');
          });
        });
      }
    });
  }



  render() {
    return (
      <View style={styles.container}>
          <TouchableHighlight style={styles.itemView} underlayColor="red" onPress={this.setData.bind(this,"我是小刀")}>
              <Text style={styles.itemText}>
                1、存储数据
              </Text>
          </TouchableHighlight>

          <TouchableHighlight style={styles.itemView} underlayColor="red" onPress={this.delData.bind(this)}>
              <Text style={styles.itemText}>
                2、删除数据
              </Text>
          </TouchableHighlight>

          <Text style={{paddingTop:40}}>
            AsyncStorage存储的值是:{this.state.data}
          </Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f2f2f2',
    paddingTop:20,
  },
  itemView:{
    backgroundColor:'grey',
    height:44,
    width:width,
    justifyContent:'center',
    marginTop:10,
  },
  itemText:{
    fontSize:15,
    color:'#ffffff',
    textAlign:'left',
    marginLeft:20,
  },
});

购物车结算示例

示例代码:

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,
        marginRight: 5,
        padding:5 ,
        borderWidth: 1,
        height: 30,
        borderRadius: 3,
        borderColor: '#ddd',
    },

    list_item_desc : {
        flex: 2,
        fontSize: 15,
    },

    list_item_price: {
        flex: 1,
        textAlign: 'right',
        fontSize: 15,
    },

    clear: {
        marginTop : 10,
        backgroundColor: '#fff',
        color: '#000',
        borderColor: '#ddd',
        borderWidth:1,
        marginLeft: 10,
        marginRight:10,
        lineHeight: 24,
        height:33,
        fontSize: 18,
        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>
        )
    },

    componentDidMount: function() {
        var _that = this;
        AsyncStorage.getAllKeys(function(err,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:[],
                    price:0,
                    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将购物车组件加载。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏王磊的博客

jQuery 计时器(jquery timers)简单应用

jquery timers 代码(版本1.2): /** * jQuery.timers - Timer abstractions for jQuery *...

32530
来自专栏葡萄城控件技术团队

WPF/Silverlight Layout 系统概述——Arrange

上一篇我们介绍了WPF/Silverlight Layout系统的Measure过程,本文将继续介绍Arrange过程。 Arrange过程概述 普通基类属性对...

21490
来自专栏华章科技

10个非常实用的Excel技巧

Excel可以说是MS Office系列中最神奇也最重要的软件。对于专业的职场人士,工作中经常需要用到Excel来分析数据。亲们别再傻傻地用鼠标点来点去啦,用这...

17280
来自专栏林德熙的博客

WPF 使用 SharpDX

先介绍一下 SharpDx ,一个底层封装的 DirectX 库,支持 AnyCpu ,支持 Direct3D9, Direct3D11, Direct3D12...

25510
来自专栏Coding迪斯尼

VUE+WebPack前端游戏设计:实现外星人的动态下滑特效

12620
来自专栏tkokof 的技术,小趣及杂念

HGE系列之三 渐入佳境

前两次“乱七八糟”的讲述了一些HGE的基础知识,不知看过的朋友有何感想,反正我自己都觉着有些不知所谓(!),但本着坚持到底的原则,今天继续献上拙文一篇,如果有朋...

10520
来自专栏阿凯的Excel

动态显示下拉框内容

过了冬至,你在北方瑟瑟发抖,我在广东秋风瑟瑟~ 最近小编经常梦回母校~放一张母校的美图! 年底了,又到了预订报刊的时候! 肯定有人会问,这年头还有谁看报刊...

31430
来自专栏程序员互动联盟

【专业文章】六种常见的HTML5写法误用(二)

四、figure元素的常见错误 figure以及figcaption的正确使用,确实是难以驾驭。让我们来看看一些常见的错误, 不是所有的图片都是figure 上...

30150
来自专栏hbbliyong

Unity3D学习笔记第一课

第一课程: 1.Unity类名必须与文件名保持一致 2.讲属性设置为public可以在Unity中访问 public float speed; // ...

39370
来自专栏GIS讲堂

Arcgis for JS扩展GraphicLayer实现区域对象的聚类统计与展示

分省市雨量站的数目通过统计表的形式在页面端展示,位置根据XY坐标信息将雨量站标绘在图上。

14520

扫码关注云+社区

领取腾讯云代金券