React Native MMKV完整封装

目录

一、架构

二、核心封装

三、数据隔离加密封装


一、架构

├─mmkv

│ │ index.ts

│ │

│ ├─adapters

│ │ BaseManager.ts

│ │ BaseStorage.ts

│ │ index.ts

│ │ LocalStorage.ts

│ │ storageFactory.ts

│ │ StorageManager.ts

│ │

│ ├─constants

│ │ index.ts

│ │ user.ts

│ │

│ ├─instances

│ │ appStorage.ts

│ │ cacheStorage.ts

│ │ userStorage.ts

│ │

│ └─utils

│ keyGenerator.ts

核心封装 LocalStorage.ts,用户数据隔离加密封装管理StorageManager.ts。

二、核心封装

BaseStorage.ts

javascript 复制代码
/**
 * @author Dragon Wu
 * @created 2026/01/25 20:46
 * @description MMKV封装对象的基类型
 */

interface BaseStorage {
  set<T = unknown>(key: string, value: T): void;
  get<T = unknown>(key: string): T | null;
  remove(key: string): void;
  clear(): void;
  setString(key: string, value: string): void;
  getString(key: string): string | null;
  setNumber(key: string, value: number): void;
  getNumber(key: string): number | null;
  setBoolean(key: string, value: boolean): void;
  getBoolean(key: string): boolean | null;
  setObject<T extends object>(key: string, value: T): void;
  getObject<T extends object>(key: string): T | null;
  setBuffer(key: string, value: ArrayBuffer): void;
  getBuffer(key: string): ArrayBuffer | null;
  has(key: string): boolean;
  keys(): string[];
  getMulti<T = unknown>(keys: string[]): Record<string, T | null>;
  setMulti(items: Array<{ key: string; value: unknown }>): void;
  addListener(callback: (key: string) => void): { clearListener: () => void };
}

export default BaseStorage;

LocalStorage.ts

javascript 复制代码
/**
 * @author Dragon Wu
 * @created 2026/01/26 20:49
 * @description 本地数据管理 适用于范围隔离的数据,如:用户数据,数据都是加密存储的
 */

import { isBlank } from '@/utils/string';
import LocalStorage from './LocalStorage';
import { createSecureStorage } from './storageFactory';
import BaseManager from './BaseManager';

export default class StorageManager implements BaseManager {
  private currentId: string | null = null;
  private storages = new Map<string, LocalStorage>();
  private secret: string | undefined; // 加密密钥种子

  constructor(secret?: string) {
    this.secret = secret;
  }

  getCurrentStorage(): LocalStorage | null {
    return this.currentId ? (this.storages.get(this.currentId) ?? null) : null;
  }

  getCurrentId(): string | null {
    return this.currentId;
  }

  switchStorage(storageId: string): LocalStorage {
    if (isBlank(storageId)) {
      throw Error('switchStorage: storageId is required');
    }

    let storage = this.storages.get(storageId);

    if (!storage) {
      storage = createSecureStorage(storageId, this.secret);
      this.storages.set(storageId, storage);
    }

    this.currentId = storageId;
    return storage;
  }

  clearStorage(storageId: string): void {
    const storage = this.storages.get(storageId);
    if (storage) {
      storage.clear();
      this.storages.delete(storageId);
    }

    if (this.currentId === storageId) {
      this.currentId = null;
    }
  }

  getAllStorageIds(): string[] {
    return Array.from(this.storages.keys());
  }

  cleanup(): void {
    this.storages.clear();
    this.currentId = null;
  }
}

使用方法:

cacheStorage.ts

javascript 复制代码
/**
 * @author Dragon Wu
 * @created 2026/01/25 20:46
 * @description 缓存实例
 */

import { createStorage } from '@/stores/mmkv/adapters';
import { STORAGE_KEYS } from '@/stores/mmkv/constants';

export const cacheStorage = createStorage(STORAGE_KEYS.CACHE);

三、数据隔离加密封装

一般用于应用级加密存储用户数据。

keyGenerator.ts

javascript 复制代码
/**
 * @author Dragon Wu
 * @created 2026/01/25 22:08
 * @description 动态加密key生成器 场景:MMVK加密key
 */

export const generateKey = (id: string): string => {
  const cleanId = id.trim();
  if (!cleanId) throw new Error('generateKey: id不能为空');

  const APP_SALT = 'scoped_storage_fixed_salt_2026_v1_secure';
  const seed = `v1:${cleanId}:${APP_SALT}`;

  // 改良的DJB2算法(完全无位运算)
  let hash = 5381;

  for (let i = 0; i < seed.length; i++) {
    // 标准DJB2: hash = hash * 33 + charCode
    // 33 = 32 + 1 = (hash << 5) + hash
    hash = hash * 32 + hash + seed.charCodeAt(i);

    // 保持在32位范围内
    if (hash > 0xffffffff) {
      hash = hash % 0xffffffff;
    }
  }

  // 使用36进制增加熵值
  const base36 = Math.abs(hash).toString(36);
  const keyBase = `sk_${base36}_${cleanId.substring(0, 4)}`;

  // 固定32字符
  return keyBase.padEnd(32, '_').substring(0, 32);
};

storageFactory.ts

javascript 复制代码
/**
 * @author Dragon Wu
 * @created 2026/01/26 20:49
 * @description 数据生产工厂
 */

import { Configuration } from 'react-native-mmkv';
import LocalStorage from './LocalStorage';
import { generateKey } from '@/stores/mmkv/utils/keyGenerator';

/**
 * 创建加密存储(用于敏感数据,特别敏感的数据不要使用MMKV,需使用Keychain)
 * @param storageId - 存储的唯一标识
 * @param secret - 加密密钥种子
 * @param config - 额外配置
 */
export const createSecureStorage = (storageId: string, secret?: string, config?: Configuration) => {
  return new LocalStorage({
    ...(config ?? {}),
    id: storageId,
    encryptionKey: generateKey(secret ? `${secret}:${storageId}` : storageId)
  });
};

/**
 * 创建普通存储(用于非敏感数据)
 * @param storageId - 存储的唯一标识
 * @param config - 额外配置
 */
export const createStorage = (storageId: string, config?: Configuration) => {
  return new LocalStorage({
    ...(config ?? {}),
    id: storageId
  });
};

BaseManager.ts

javascript 复制代码
/**
 * @author Dragon Wu
 * @created 2026/01/26 20:46
 * @description StorageManager的实现接口
 */

import LocalStorage from './LocalStorage';

interface BaseManager {
  getCurrentStorage(): LocalStorage | null;
  getCurrentId(): string | null;
  switchStorage(storageId: string): LocalStorage;
  clearStorage(storageId: string): void;
  getAllStorageIds(): string[];
  cleanup(): void;
}

export default BaseManager;

StorageManager.ts

javascript 复制代码
/**
 * @author Dragon Wu
 * @created 2026/01/26 20:49
 * @description 本地数据管理 适用于范围隔离的数据,如:用户数据,数据都是加密存储的
 */

import { isBlank } from '@/utils/string';
import LocalStorage from './LocalStorage';
import { createSecureStorage } from './storageFactory';
import BaseManager from './BaseManager';

export default class StorageManager implements BaseManager {
  private currentId: string | null = null;
  private storages = new Map<string, LocalStorage>();
  private secret: string | undefined; // 加密密钥种子

  constructor(secret?: string) {
    this.secret = secret;
  }

  getCurrentStorage(): LocalStorage | null {
    return this.currentId ? (this.storages.get(this.currentId) ?? null) : null;
  }

  getCurrentId(): string | null {
    return this.currentId;
  }

  switchStorage(storageId: string): LocalStorage {
    if (isBlank(storageId)) {
      throw Error('switchStorage: storageId is required');
    }

    let storage = this.storages.get(storageId);

    if (!storage) {
      storage = createSecureStorage(storageId, this.secret);
      this.storages.set(storageId, storage);
    }

    this.currentId = storageId;
    return storage;
  }

  clearStorage(storageId: string): void {
    const storage = this.storages.get(storageId);
    if (storage) {
      storage.clear();
      this.storages.delete(storageId);
    }

    if (this.currentId === storageId) {
      this.currentId = null;
    }
  }

  getAllStorageIds(): string[] {
    return Array.from(this.storages.keys());
  }

  cleanup(): void {
    this.storages.clear();
    this.currentId = null;
  }
}

使用案例:

userStorage.ts

javascript 复制代码
/**
 * @author Dragon Wu
 * @created 2026/01/27
 * @description 用户存储管理器
 */

import { StorageManager } from '@/stores/mmkv/adapters';
import { STORAGE_KEYS } from '@/stores/mmkv/constants';

const userManager = new StorageManager(STORAGE_KEYS.USER);

export default userManager;

总结到此!

相关推荐
晚霞的不甘2 小时前
Flutter for OpenHarmony 电商 App 搜索功能深度解析:从点击到反馈的完整实现
开发语言·前端·javascript·flutter·前端框架
前端(从入门到入土)2 小时前
解决Webpack打包白屏报错问题l.a.browse is not a function
前端·javascript
Jul1en_2 小时前
【Web自动化测试】Selenium常用函数+IDEA断言配置
前端·selenium·intellij-idea
Marshmallowc2 小时前
从源码深度解析 React:Hook 如何在 Fiber 中存储?DOM Ref 如何绑定?
前端·react.js·前端框架·fiber
Eiceblue2 小时前
Vue文档编辑器(Word默认功能)示例
前端·vue.js·word
Mr Xu_2 小时前
在 Vue 3 中集成 WangEditor 富文本编辑器:从基础到实战
前端·javascript·vue.js
No Silver Bullet2 小时前
HarmonyOS NEXT开发进阶(二十三):多端原生App中通过WebView嵌套Web应用实现机制
前端·华为·harmonyos
光影少年2 小时前
react和vue中的优点和缺点都有哪些
前端·vue.js·react.js
web_Hsir2 小时前
uniapp + vue2 + pfdjs + web-view 实现安卓、iOS App PDF预览
android·前端·uni-app