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;

总结到此!

相关推荐
_AaronWong15 小时前
Electron 实现仿豆包划词取词功能:从 AI 生成到落地踩坑记
前端·javascript·vue.js
cxxcode15 小时前
I/O 多路复用:从浏览器到 Linux 内核
前端
用户54330814419415 小时前
AI 时代,前端逆向的门槛已经低到离谱 — 以 Upwork 为例
前端
JarvanMo15 小时前
Flutter 版本的 material_ui 已经上架 pub.dev 啦!快来抢先体验吧。
前端
JohnYan15 小时前
工作笔记-CodeBuddy应用探索
javascript·ai编程·aiops
恋猫de小郭16 小时前
AI 可以让 WIFI 实现监控室内人体位置和姿态,无需摄像头?
前端·人工智能·ai编程
哀木16 小时前
给自己整一个 claude code,解锁编程新姿势
前端
程序员鱼皮16 小时前
GitHub 关注突破 2w,我总结了 10 个涨星涨粉技巧!
前端·后端·github
UrbanJazzerati16 小时前
Vue3 父子组件通信完全指南
前端·面试
是一碗螺丝粉16 小时前
5分钟上手LangChain.js:用DeepSeek给你的App加上AI能力
前端·人工智能·langchain