React Native 一站式解决方案(一)AsyncStorage

2020-05-12 16:30:41 +08:00
 rufeng008

react-native-easy-app 是一款为 React Native App 快速开发提供基础服务的纯 JS 库(支持 IOS & Android),特别是在从 0 到 1 的项目搭建初期,至少可以为开发者减少 30%的工作量。

react-native-easy-app 主要做了这些工作:

1. 对 AsyncStorage 进行封装,开发者只需几行代码即可实现一个持久化数据管理器。

2. 对 fetch 进行封装,使得开发者只需关注当前 App 的前后台交互逻辑和协议,定义好参数设置及解析逻辑即可。

3. 重新封装了 RN 的 View 、Text 、Image 、FlatList 使用得这些控件在适当的时候支持事件或支持 icon 与文本,能有效减少布局中的嵌套逻辑。

4. 通过设置一个屏幕参考尺寸,重置 XView 、XText 、XImage 的尺寸,实现自动多屏适配

可能有人觉得,RN 的 AsyncStorage 本身就很简单,自己封装也就几十行代码的工作量,为什么还要使用第三方库?

一千个人心中,有一千个哈姆雷特,也许我的封装思路能给你带来不一样的启发也未可知呢?

数据存储( AsyncStorage )

RN 平台提供的 AsyncStorage 有一些基础方法:setItem,getItem,removeItem,getAllKeys,这些是 promise 模式的并且 AsyncStorage 只支持对纯字符串的存取,因此我们不便于直接在代码中去直接调用这些方法,我们得对 AsyncStorage 做一次封装,怎样封装能使我们更方便快捷的访问本地存取呢?

我们来看下通过 react-native-easy-app 库的 XStorage,我们可以怎样访问 AsyncStorage:

1 、核心代码实现
import { XStorage } from 'react-native-easy-app';

let RNStorage = { // 自定义对象
    hasLogin: undefined,
    customerId: undefined,
    userInfo: undefined
};
XStorage.initStorage(RNStorage, () => { // 初始化自定义数据管理器
    RNStorage.customerId = '123456';
    RNStorage.hasLogin = true;
    RNStorage.userInfo = {name: 'zhangsan', age: 30};
    console.log(JSON.stringify(RNStorage)) // 打印数据管理器的内容
})

执行完上面的代码后我们看看控制台输出:

再通过 Root Explorer 查看一下当前 App 的 data/data/{package}/database 下数据表的内容:

**😲什么?**上面的代码中并没有做任何数据库的存储操作啊,为什么赋值给 RNStorage 的数据却被存到了本地数据库中呢?我们先看上面的代码中做了什么:

  1. 定义了一个自定义对象 RNStorage
  2. 将自定义对象传给 XStorage.initStorage 进行初始化
  3. 在初始化完成后对 RNStorage 的属性进行了赋值
  4. 打印 RNStorage 的内容

由此可见,数据的存储操作必定是上面的第 2 、3 步引起的。我们进入XStorage的源码看看,里面做了什么:

Object.keys(targetObj).map(key => {
    const keyStr = newKey(Tag, key);
    Object.defineProperty(targetObj, key, {
        get: () => {
            return this[keyStr]
        },
        set: (value) => {
            try {
                this[keyStr] = value;
                const valueStr = (typeof value === 'object') ? JSON.stringify(value) : String(value);
                keyValuesPairs.push([keyStr, valueStr])
            } catch (exception) {
                console.log(exception && exception.message);
            }
        },
    })
});
setInterval(() => {
    if (!isEmpty(keyValuesPairs)) {
        let saveDataArray = [...keyValuesPairs];
        keyValuesPairs = []; //清空原键值对数组
        AsyncStorage.multiSet(saveDataArray, () => {
            dataChangedCallback && dataChangedCallback(saveDataArray)
        });
    }
}, 2500)
const Keys = Object.keys(storageObj);
const StorageKeys = Keys.map(key => newKey(Tag, key));
// 初始化时,将 AsyncStorage 中的数据一次性读取到内存中
AsyncStorage.multiGet(StorageKeys).then(keyValuePairs => {
    keyValuePairs.map(([keyStr, value]) => {
        let [, key] = keyStr.split(splitTag);
        if (persistTag !== key && !isEmpty(value)) {
            storageObj[key] = convertData(value)
        }
    });
    setTimeout(() => initializedCallback(), 100)
}).catch(error => {
    console.log(error)
})

哦,原来 XStorage 通过 getter 、setter 生成器,将用户自定义的 RNStorage 的各属与 AsyncStorage 的数据表各字段的值进行了关联形成了一个绑定关系,在当用户对 RNStorage 的各属性进行赋值、取值操作的时候,实际上会触发 getter 、setter 生成器,相应的会对 AsyncStorage 中的数据表进行读写操作。

效率与性能的平衡

至此就完全清楚了,是不是很简单?开发者通过 react-native-easy-app 只需定义一个全局可导出的 RNStorage 对象(命名随意,并定义好 App 所需的各属性字段),然后在 App 启动的时候通过 XStorage 初始化一次 RNStorage 即可,以后直接访问 RNStorage 中的属性值就行了(所有对 RNStorage 属性的修改都会被自动同步到 AsyncStorage 中),完全是一劳永逸啊。。。

###react-native-easy-app 详解与使用之(二) fetch

想进一步了解,请移步至 npm 或 github 查看 react-native-easy-app,有源码及使用示例,待大家一探究竟,欢迎朋友们 Star !

如果有任何疑问,欢迎扫码加入 RN 技术 QQ 交流群

833 次点击
所在节点    程序员
0 条回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/670971

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX