數據持久化一直都是軟件開發中重要的一個環節,幾乎全部的應用都具有這一項功能;那什麼是數據持久化呢?—— 說白了就是數據的本地化存儲,將數據存儲到本地,在須要的時候進行調用。html
這邊咱們介紹兩種在 React-Native 中比較經常使用的存儲方式node
NSUserDefault
,區別在於,AsyncStorage
只能存儲 字符串鍵值對,而 NSUserDefault
能夠存儲 字符串和number。接下來咱們就來看看怎麼使用它們。react
AsyncStorage方法官方文檔寫得很詳細,這邊就不對贅述了!android
AsyncStorage 使用方法很簡單,咱們就直接上代碼:ios
// 增長 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,咱們能夠直接使用它,方法很簡單,說明文檔中說得很詳細。git
既然是第三方框架,那麼第一部確定就是導入到咱們的工程中:github
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
文件確定是最早調用的,它們纔是真正的王)。web
然而,爲了方便咱們使用同一套代碼,咱們會建立一個 Main
文件做爲程序入口的 中轉總站
來管理其餘的文件,而後外界只要調用這個 Main
文件,就能夠展現裏面的全部東西。因此,將引用
放到 Main
文件中是最好的選擇。sql
// 在 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 也支持了 React-Native ,這樣咱們能夠在移動端 愉快地
進行存儲操做了。
並且使用方法 Realm 官方提供的文檔都一如既往地詳細,因此若是感興趣,也能夠到 Realm說明文檔 進行學習(不知是網絡問題仍是官方沒有整理好,我這邊中文版文檔是打不開的,因此只能看英文版),這邊咱們直接將裏面經常使用到的內容整理出來,簡單說下怎麼使用。
首先,同樣仍是須要打開終端將 Realm 放到咱們的工程中
npm install --save realm
接着,添加 Realm 與 工程的連接
react-native link realm
rnpm link realm
APP
並從新安裝(Xcode會進行一系列配置,其中會在網絡下載一下必要的組件,時間視網絡狀況而定),來測試下安卓和iOS,2端是否能正常使用若是出現有 err!
等字樣或者在安卓中出現錯誤警告,說明安卓端沒有成功地進行所有配置,須要咱們手動進行配置,步驟以下:
若是出現 android Missing Realm constructor - please ensure RealmReact framework is included
報錯:
MainApplication
中添加new RealmReactPackage()
若是仍是連接不上,咱們檢查如下幾處代碼是否有自動添加
include ':realm' project(':realm').projectDir = new File(rootProject.projectDir, '../node_modules/realm/android')
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
增刪改查
這老四樣,使用以前,仍是老規矩,初始化表格:
// 新建表模型 const PersonSchema = { name: 'Person', primaryKey:'id', // 官方沒給出自增加的辦法,並且通常不會用到主鍵,這也解決了重複訪問的問題,並且實際開發中咱們不須要主鍵的,讓服務端管就是了 properties: { id:'int', name: 'string', tel_number: {type: 'string', default: '156xxxxxxxx'}, // 添加默認值的寫法 city: 'string' // 直接賦值的方式設置類型 } };
// 根據提供的表初始化 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); }) }
轉載自:https://www.jianshu.com/p/78b4b4b9d041