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;

总结到此!

相关推荐
大橙子额37 分钟前
【解决报错】Cannot assign to read only property ‘exports‘ of object ‘#<Object>‘
前端·javascript·vue.js
WooaiJava2 小时前
AI 智能助手项目面试技术要点总结(前端部分)
javascript·大模型·html5
LYFlied2 小时前
从 Vue 到 React,再到 React Native:资深前端开发者的平滑过渡指南
vue.js·react native·react.js
爱喝白开水a2 小时前
前端AI自动化测试:brower-use调研让大模型帮你做网页交互与测试
前端·人工智能·大模型·prompt·交互·agent·rag
Never_Satisfied2 小时前
在JavaScript / HTML中,关于querySelectorAll方法
开发语言·javascript·html
董世昌412 小时前
深度解析ES6 Set与Map:相同点、核心差异及实战选型
前端·javascript·es6
WeiXiao_Hyy3 小时前
成为 Top 1% 的工程师
java·开发语言·javascript·经验分享·后端
吃杠碰小鸡3 小时前
高中数学-数列-导数证明
前端·数学·算法
kingwebo'sZone3 小时前
C#使用Aspose.Words把 word转成图片
前端·c#·word
xjt_09014 小时前
基于 Vue 3 构建企业级 Web Components 组件库
前端·javascript·vue.js