前言


  • 因为 实战项目系列 涉及到数据持久化,这边就来补充一下。
  • 如本文有错或理解偏差欢迎联系我,会尽快改正更新!
  • 如有什么问题,也可直接通过邮箱 277511806@qq.com 联系我。

数据持久化


  • 数据持久化一直都是软件开发中重要的一个环节,几乎所有的应用都具备这一项功能;那什么是数据持久化呢?—— 说白了就是数据的本地化存储,将数据存储到本地,在需要的时候进行调用。

  • 这边我们介绍两种在 React-Native 中比较常用的存储方式

    • AsyncStorage:这是官方使用的存储方式,类似于 iOS 中的 NSUserDefault ,区别在于,AsyncStorage 只能存储 字符串键值对,而 NSUserDefault 可以存储 字符串和number
    • Realm:今天才发现 Realm 也已经支持 React-Native ,这是新兴的移动端数据存储方式,在没有它之前,一直都是使用 sqlist 进行数据存储,在性能上,各有优势,但是操作上,Realm 有着明显优势,更方便使用。
  • 接下来我们就来看看怎么使用它们。

AsyncStorage 简单使用


  • AsyncStorage方法官方文档写得很详细,这边就不对赘述了!

  • AsyncStorage 使用方法很简单,我们就直接上代码:

	// 增加
createData() {
AsyncStorage.setItem('name', JSON.stringify('吉泽明步'), (error, result) => {
if (!error) {
this.setState({
data:'保存成功!'
})
}
});
} // 查询
inquireData() {
AsyncStorage.getItem('name')
.then((value) => {
let jsonValue = JSON.parse((value)); this.setState({
data:jsonValue
})
})
} // 更新
upData() {
AsyncStorage.setItem('name', JSON.stringify('苍井空'), (error, result) => {
if (!error) {
this.setState({
data:'更新成功!'
})
}
});
} // 删除
removeData() {
AsyncStorage.removeItem('name'); this.setState({
data:'删除完成!'
})
}

  • 按照官方推荐,我们使用 AsyncStorage 前,最好进行一层封装,React-Native中文网 给我们提供了一个比较好的框架 —— react-native-storage,我们可以直接使用它,方法很简单,说明文档中说得很详细。

  • 既然是第三方框架,那么第一部肯定就是导入到我们的工程中:

	npm install react-native-storage --save

  • 接着,我们根据创建一个 Storage 文件专门对框架进行初始化操作:
	import {
AsyncStorage,
} from 'react-native'; // 第三方框架
import Storage from 'react-native-storage'; var storage = new Storage({
// 最大容量,默认值1000条数据循环存储
size: 1000, // 存储引擎:对于RN使用AsyncStorage,对于web使用window.localStorage
// 如果不指定则数据只会保存在内存中,重启后即丢失
storageBackend: AsyncStorage, // 数据过期时间,默认一整天(1000 * 3600 * 24 毫秒),设为null则永不过期
defaultExpires: 1000 * 3600 * 24, // 读写时在内存中缓存数据。默认启用。
enableCache: true, // 如果storage中没有相应数据,或数据已过期,
// 则会调用相应的sync方法,无缝返回最新数据。
// sync方法的具体说明会在后文提到
// 你可以在构造函数这里就写好sync的方法
// 或是写到另一个文件里,这里require引入
// 或是在任何时候,直接对storage.sync进行赋值修改
sync: require('./sync')
}) // 全局变量
global.storage = storage;
  • 到这里,我们需要注意的就是要在哪里初始化这个文件,其实一个思路就是 —— 在哪个地方,我们只需要引用一次文件,就可以在其他文件中使用(比如:我们程序默认的进口就是 index.ios/android.js 文件,那么只要在他们中引用一次文件即可,这样就不需要去注意什么调用顺序,因为 index.ios/android.js 文件肯定是最先调用的,它们才是真正的王)。

  • 然而,为了方便我们使用同一套代码,我们会创建一个 Main 文件作为程序入口的 中转总站 来管理其他的文件,然后外界只要调用这个 Main 文件,就可以展示里面的所有东西。所以,将引用放到 Main 文件中是最好的选择。


// 在 main 文件中添加
import storage from '封装的文件位置';
  • 到这里,我们就完成了最基础的配置,我们只需要在需要用到的地方直接使用就可以了,首先我们在新建一个文件,然后从Main文件跳转到这个文件中。

  • 接着,我们就真正地自己来使用一下这个框架:

	    // 增加
createData() {
// 使用key保存数据
storage.save({
key:'storageTest', // 注意:请不要在key中使用_下划线符号!
rawData: {
name:'吉泽明步',
city:'xx省xxx市'
}, // 设为null,则不过期,这里会覆盖初始化的时效
expires: 1000 * 3600
});
} // 查询
inquireData() {
storage.load({
key:'storageTest', // autoSync(默认为true)意味着在没有找到数据或数据过期时自动调用相应的sync方法
autoSync: true, // syncInBackground(默认为true)意味着如果数据过期,
// 在调用sync方法的同时先返回已经过期的数据。
// 设置为false的话,则始终强制返回sync方法提供的最新数据(当然会需要更多等待时间)。
syncInBackground: true, // 你还可以给sync方法传递额外的参数
syncParams: {
extraFetchOptions: {
// 各种参数
},
someFlag: true,
},
}).then(ret => {
// 如果找到数据,则在then方法中返回
// 注意:这是异步返回的结果(不了解异步请自行搜索学习)
// 你只能在then这个方法内继续处理ret数据
// 而不能在then以外处理
// 也没有办法“变成”同步返回
// 你也可以使用“看似”同步的async/await语法 // 更新data值
this.setState({
data: ret.name
}); }).catch(err => {
//如果没有找到数据且没有sync方法,
//或者有其他异常,则在catch中返回
console.warn(err.message);
switch (err.name) {
case 'NotFoundError':
// 更新
this.setState({
data:'数据为空'
}); break;
case 'ExpiredError':
// TODO
break;
}
})
} // 更新
upData() {
// 重新存储即可
storage.save({
key:'storageTest', // 注意:请不要在key中使用_下划线符号!
rawData: {
name:'苍井空',
city:'xx省xxx市'
}, // 设为null,则不过期,这里会覆盖初始化的时效
expires: 1000 * 3600
});
} // 删除
removeData() {
// 删除单个数据
storage.remove({
key: 'storageTest'
}); // storage.remove({
// key: 'react-native-storage-test',
// name:'吉泽明步'
// }); // // !! 清空map,移除所有"key-id"数据(但会保留只有key的数据)
// storage.clearMap();
//
// // 获取某个key下的所有id
// storage.getIdsForKey('user').then(ids => {
// console.log(ids);
// });
//
// // 获取某个key下的所有数据
// storage.getAllDataForKey('user').then(users => {
// console.log(users);
// });
//
// // !! 清除某个key下的所有数据
// storage.clearMapForKey('user');
}

Realm 配置与常见错误处理


  • 很惊喜,Realm 也支持了 React-Native ,这样我们可以在移动端 愉快地 进行存储操作了。

  • 而且使用方法 Realm 官方提供的文档都一如既往地详细,所以如果感兴趣,也可以到 Realm说明文档 进行学习(不知是网络问题还是官方没有整理好,我这边中文版文档是打不开的,所以只能看英文版),这边我们直接将里面常用到的内容整理出来,简单说下怎么使用。

  • 首先,一样还是需要打开终端将 Realm 放到我们的工程中

	npm install --save realm

  • 接着,添加 Realm 与 工程的链接

    • React-Native >= 0.31.0
    	react-native link realm
    
    
    • React-Native < 0.31.0
    	rnpm link realm
    
    

  • 出现上面的提示表示成功,然后我们需要卸载模拟器中已经安装的 APP 并重新安装(Xcode会进行一系列配置,其中会在网络下载一下必要的组件,时间视网络情况而定),来测试下安卓和iOS,2端是否能正常使用

  • 如果出现有 err! 等字样或者在安卓中出现错误警告,说明安卓端没有成功地进行全部配置,需要我们手动进行配置,步骤如下:

    • 如果出现 android Missing Realm constructor - please ensure RealmReact framework is included 报错:

      • MainApplication 中添加
      	new RealmReactPackage()
      
      
    • 如果还是链接不上,我们检查以下几处代码是否有自动添加

      • settings.gradle 中是否有下面代码,不存在手动添加
      	include ':realm'
      project(':realm').projectDir = new File(rootProject.projectDir, '../node_modules/realm/android')
      • 如果还不行,到app => build.gradle 中是否有下面代码,不存在手动添加
      	dependencies {
      compile project(':realm') // 是否存在,不存在手动添加(再旧版本有效,新版本不需要添加此项)
      compile fileTree(dir: "libs", include: ["*.jar"])
      compile "com.android.support:appcompat-v7:23.0.1"
      compile "com.facebook.react:react-native:+" // From node_modules
      }
  • 接着,重新运行安卓:

	react-native run-android

  • 如果还是不行,可联系官方,或者将错误代码发送给我,也许可以帮忙解决。

Realm 常用操作


  • 作为数据库,使用它无法就是 增删改查 这老四样,使用之前,还是老规矩,初始化表格:

    • name:表格名称。
    • primaryKey:主键,这个属性的类型可以是 'int' 和 'string',并且如果设置主键之后,在更新和设置值的时候这个值必须保持唯一性,并且无法修改。
    • properties:这个属性内放置我们需要的字段。
	// 新建表模型
const PersonSchema = {
name: 'Person',
primaryKey:'id', // 官方没给出自增长的办法,而且一般不会用到主键,这也解决了重复访问的问题,而且实际开发中我们不需要主键的,让服务端管就是了
properties: {
id:'int',
name: 'string',
tel_number: {type: 'string', default: '156xxxxxxxx'}, // 添加默认值的写法
city: 'string' // 直接赋值的方式设置类型
}
};
  • 初始化 Realm:
	// 根据提供的表初始化 Realm,可同时往数组中放入多个表
let realm = new Realm({schema: [PersonSchema]});
  • 增加数据:
	// 增加
createData() {
realm.write(() => {
realm.create('Person', {id:0, name:'吉泽明步', tel_number:'137xxxxxxxx', city:'xx省xx市xxxxxx'});
realm.create('Person', {id:1, name:'苍井空', tel_number:'137xxxxxxxx', city:'xx省xx市xxxxxx'});
realm.create('Person', {id:2, name:'小泽玛利亚', tel_number:'137xxxxxxxx', city:'xx省xx市xxxxxx'});
realm.create('Person', {id:3, name:'皮皮虾我们走', tel_number:'137xxxxxxxx', city:'xx省xx市xxxxxx'});
realm.create('Person', {id:4, name:'波多野结衣', tel_number:'137xxxxxxxx', city:'xx省xx市xxxxxx'});
})
}
  • 查询数据

    • 查询所有数据:
    	// 查询所有数据
    let persons = realm.objects('Person');
    console.log ('name:' + persons[0].name + 'city:' + persons[0].city)
    • 根据条件查询数据
    	// 查询
    inquireData() {
    let allData; // 获取Person对象
    let Persons = realm.objects('Person'); // 遍历表中所有数据
    for (let i = 0; i<Persons.length; i++) {
    let tempData = '第' + i + '个' + Persons[i].name + Persons[i].tel_number + Persons[i].city + '\n';
    allData += tempData
    } this.setState({
    data:allData
    })
    } // 根据条件查询
    filteredData() {
    let allData; // 获取Person对象
    let Persons = realm.objects('Person');
    // 设置筛选条件
    let person = Persons.filtered('id == 1'); if (person) {
    // 遍历表中所有数据
    for (let i = 0; i<person.length; i++) {
    let tempData = '第' + (person[i].id + 1) + '个数据:' + person[i].name + person[i].tel_number + person[i].city + '\n';
    allData += tempData
    }
    } this.setState({
    data:'筛选到的数据:' + allData
    })
    }
  • 更新数据:


// 更新
upData() {
realm.write(() => {
// 方式一
realm.create('Person', {id: 0, name: '皮皮虾,我们走', tel_number: '156xxxxxxxx', city: 'xx省xx市xxxxxx'}, true); // // 方式二:如果表中没有主键,那么可以通过直接赋值更新对象
// // 获取Person对象
// let Persons = realm.objects('Person');
// // 设置筛选条件
// let person = Persons.filtered('name == 苍井空');
// // 更新数据
// person.name = '黄鳝门' })
}
  • 删除数据:
	// 删除
removeData() {
realm.write(() => {
// 获取Person对象
let Persons = realm.objects('Person');
// 删除
realm.delete(Persons);
})
}

React Native 之 数据持久化的更多相关文章

  1. React Native之数据存储技术AsyncStorage

    1. 如何将数据存储到本地? 数据存储是开发APP必不可少的一部分,比如页面缓存,从网络上获取数据的本地持久化等,那么在RN中如何进行数据存储呢? RN官方推荐我们在RN中使用AsyncStorage ...

  2. 从零学React Native之13 持久化存储

    数据持久化就是指应用程序将某些数据存储在手机存储空间中. 借助native存储 这种方式不言而喻,就是把内容传递给native层,通过原生API存储,详见从零学React Native之05混合开发 ...

  3. React Native之持久化存储(AsyncStorage、react-native-storage)的使用

    AsyncStorage是一个简单的.异步的.持久化的Key-Value存储系统,它对于App来说是全局性的.这是官网上对它的介绍.可以知道,这个asyncstorage也是以键值对的形式进行存储数据 ...

  4. [RN] React Native 使用 AsyncStorage 存储 缓存数据

    React Native 使用 AsyncStorage 存储 缓存数据 AsyncStorage是一个简单的.异步的.持久化的Key-Value存储系统,它对于App来说是全局性的.这是官网上对它的 ...

  5. React Native ——实现一个简单的抓取github上的项目数据列表

    /** * Sample React Native App * https://github.com/facebook/react-native */ 'use strict'; var React ...

  6. React Native移动开发实战-3-实现页面间的数据传递

    React Native使用props来实现页面间数据传递和通信.在React Native中,有两种方式可以存储和传递数据:props(属性)以及state(状态),其中: props通常是在父组件 ...

  7. React Native 获取网络数据

    getMoviesFromApiAsync() { return fetch('http://facebook.github.io/react-native/movies.json') .then(( ...

  8. react native AsyncStorage的使用

    如果现在有一个需求,是要把用户的账号密码保存到本地,大家会怎么做的呢?如果在android中,我相信一大部分人会想到SharedPreferences,这是一个以键值对的形式进行存储的.那如果在rea ...

  9. 腾讯优测优分享 | 探索react native首屏渲染最佳实践

    腾讯优测是专业的移动云测试平台,旗下的优分享不定时提供大量移动研发及测试相关的干货~ 此文主要与以下内容相关,希望对大家有帮助. react native给了我们使用javascript开发原生app ...

随机推荐

  1. 时间处理之strtotime

    strtotime (PHP 4, PHP 5, PHP 7)strtotime - 将任何英文文本的日期时间描述解析为 Unix 时间戳说明 int strtotime ( string $time ...

  2. 微端游戏启动器launcher的制作之下载篇(系列一)

    首先第一篇先讲一讲launcher最核心的功能---下载功能. 这个部分估计得好几篇才能写完,东西比较多也比较杂,慢慢来吧,我的东西也在继续改进中...... 从web上下载文件需要用到几个类,Htt ...

  3. POJ 1308 Is It A Tree?--题解报告

    Is It A Tree? Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 31092   Accepted: 10549 D ...

  4. linux之sed的常用操作

    Sed命令: sed是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用,功能不同凡响.处理时,把当前处理的行存储在临时缓冲区中,称为"模式空间"(patter ...

  5. hadoop系列二:HDFS文件系统的命令及JAVA客户端API

    转载请在页首明显处注明作者与出处 一:说明 此为大数据系列的一些博文,有空的话会陆续更新,包含大数据的一些内容,如hadoop,spark,storm,机器学习等. 当前使用的hadoop版本为2.6 ...

  6. 康复计划#1 再探后缀自动机&后缀树

    本篇口胡写给我自己这样的东西都忘光的残废选手 以及那些刚学SAM,看了其他的一些东西并且没有完全懵逼的人 (初学者还是先去看有图的教程吧,虽然我的口胡没那么好懂,但是我觉得一些细节还是讲清楚了的) 大 ...

  7. salesforce 零基础学习(六十六)VF页面应善于使用变量和函数(二)常用函数的使用

    上一篇介绍VF中常用的变量,此篇主要内容为VF页面可以直接使用的函数,主要包括Date相关函数,Text相关函数,Information相关函数以及logic相关函数,其他相关函数,比如math相关函 ...

  8. (3)activiti流程的挂起和激活

    有时候,我们需要对一个已经执行的流程进行暂停,而不是删除它,这个时候就需要我们调用activiti暂停和激活的api来操作他们 每启动一个流程实例,都会在该流程实例下产生相应的流程任务,处于1*多的关 ...

  9. [商业_法务] 2、注册公司起名很费劲,用C++怒写个随机名字生成器

    前言 博主最近在注册公司,由于之前听说过注册公司的名字很难通过,于是便直接找代理去帮忙跑趟,为确保万无一失,还自己绞尽脑汁想了几个很奇葩的名字(噬菌体.云木.灌木.杏仁...). 但是不幸的是那些奇葩 ...

  10. 简洁、轻量的前端UI框架 - Hbook

    Simple, lightweight front-end UI framework Get Start : http://www.bookcss.com Introduce Hbook focus ...