Ionic本地存储 #

一、存储概述 #

1.1 存储方案对比 #

方案 容量 持久性 适用场景
localStorage 5-10MB 持久 简单数据
Capacitor Storage 无限制 持久 键值对数据
SQLite 无限制 持久 结构化数据
IndexedDB 大容量 持久 复杂数据

1.2 选择建议 #

text
简单键值对 → Capacitor Storage
结构化数据 → SQLite
大量数据 → IndexedDB
临时数据 → 内存

二、Capacitor Storage #

2.1 安装 #

bash
npm install @capacitor/preferences
npx cap sync

2.2 基本使用 #

typescript
import { Preferences } from '@capacitor/preferences';

// 存储
async setItem(key: string, value: any) {
  await Preferences.set({
    key,
    value: JSON.stringify(value)
  });
}

// 获取
async getItem(key: string): Promise<any> {
  const { value } = await Preferences.get({ key });
  return value ? JSON.parse(value) : null;
}

// 删除
async removeItem(key: string) {
  await Preferences.remove({ key });
}

// 清空
async clearAll() {
  await Preferences.clear();
}

// 获取所有键
async getAllKeys(): Promise<string[]> {
  const { keys } = await Preferences.keys();
  return keys;
}

2.3 存储服务封装 #

typescript
// services/storage.service.ts
import { Injectable } from '@angular/core';
import { Preferences } from '@capacitor/preferences';

@Injectable({
  providedIn: 'root'
})
export class StorageService {
  
  async set(key: string, value: any): Promise<void> {
    await Preferences.set({
      key,
      value: JSON.stringify(value)
    });
  }
  
  async get<T>(key: string): Promise<T | null> {
    const { value } = await Preferences.get({ key });
    return value ? JSON.parse(value) : null;
  }
  
  async remove(key: string): Promise<void> {
    await Preferences.remove({ key });
  }
  
  async clear(): Promise<void> {
    await Preferences.clear();
  }
  
  async keys(): Promise<string[]> {
    const { keys } = await Preferences.keys();
    return keys;
  }
}

2.4 使用示例 #

typescript
import { Component } from '@angular/core';
import { StorageService } from './storage.service';

@Component({
  selector: 'app-settings',
  templateUrl: 'settings.page.html'
})
export class SettingsPage {
  settings = {
    notifications: true,
    darkMode: false,
    language: 'zh-CN'
  };
  
  constructor(private storage: StorageService) {
    this.loadSettings();
  }
  
  async loadSettings() {
    const settings = await this.storage.get('settings');
    if (settings) {
      this.settings = settings;
    }
  }
  
  async saveSettings() {
    await this.storage.set('settings', this.settings);
  }
}

三、SQLite存储 #

3.1 安装 #

bash
npm install @capacitor-community/sqlite
npx cap sync

3.2 数据库服务 #

typescript
// services/database.service.ts
import { Injectable } from '@angular/core';
import { CapacitorSQLite, SQLiteConnection, SQLiteDBConnection } from '@capacitor-community/sqlite';

@Injectable({
  providedIn: 'root'
})
export class DatabaseService {
  private sqlite: SQLiteConnection;
  private db: SQLiteDBConnection | null = null;
  private dbName = 'myapp_db';
  
  constructor() {
    this.sqlite = new SQLiteConnection(CapacitorSQLite);
  }
  
  async init(): Promise<void> {
    try {
      // 创建数据库连接
      this.db = await this.sqlite.createConnection(
        this.dbName,
        false,
        'no-encryption',
        1
      );
      
      // 打开数据库
      await this.db.open();
      
      // 创建表
      await this.createTables();
    } catch (error) {
      console.error('数据库初始化失败:', error);
    }
  }
  
  private async createTables(): Promise<void> {
    const createUsersTable = `
      CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT NOT NULL,
        email TEXT UNIQUE NOT NULL,
        created_at DATETIME DEFAULT CURRENT_TIMESTAMP
      )
    `;
    
    await this.db?.execute(createUsersTable);
  }
  
  // 插入用户
  async insertUser(user: { name: string; email: string }): Promise<number> {
    const result = await this.db?.run(
      'INSERT INTO users (name, email) VALUES (?, ?)',
      [user.name, user.email]
    );
    return result?.changes?.lastId || 0;
  }
  
  // 获取所有用户
  async getUsers(): Promise<any[]> {
    const result = await this.db?.query('SELECT * FROM users');
    return result?.values || [];
  }
  
  // 获取单个用户
  async getUser(id: number): Promise<any> {
    const result = await this.db?.query(
      'SELECT * FROM users WHERE id = ?',
      [id]
    );
    return result?.values?.[0] || null;
  }
  
  // 更新用户
  async updateUser(id: number, user: { name: string; email: string }): Promise<void> {
    await this.db?.run(
      'UPDATE users SET name = ?, email = ? WHERE id = ?',
      [user.name, user.email, id]
    );
  }
  
  // 删除用户
  async deleteUser(id: number): Promise<void> {
    await this.db?.run('DELETE FROM users WHERE id = ?', [id]);
  }
}

3.3 使用示例 #

typescript
import { Component, OnInit } from '@angular/core';
import { DatabaseService } from './database.service';

@Component({
  selector: 'app-users',
  templateUrl: 'users.page.html'
})
export class UsersPage implements OnInit {
  users: any[] = [];
  
  constructor(private db: DatabaseService) {}
  
  async ngOnInit() {
    await this.db.init();
    await this.loadUsers();
  }
  
  async loadUsers() {
    this.users = await this.db.getUsers();
  }
  
  async addUser() {
    const id = await this.db.insertUser({
      name: '新用户',
      email: 'user@example.com'
    });
    await this.loadUsers();
  }
}

四、IndexedDB存储 #

4.1 使用Dexie.js #

bash
npm install dexie

4.2 数据库定义 #

typescript
// services/indexed-db.service.ts
import { Injectable } from '@angular/core';
import Dexie, { Table } from 'dexie';

export interface User {
  id?: number;
  name: string;
  email: string;
  createdAt: Date;
}

export class AppDatabase extends Dexie {
  users!: Table<User, number>;
  
  constructor() {
    super('MyAppDatabase');
    
    this.version(1).stores({
      users: '++id, name, email, createdAt'
    });
  }
}

@Injectable({
  providedIn: 'root'
})
export class IndexedDbService {
  private db: AppDatabase;
  
  constructor() {
    this.db = new AppDatabase();
  }
  
  // 添加用户
  async addUser(user: Omit<User, 'id' | 'createdAt'>): Promise<number> {
    return await this.db.users.add({
      ...user,
      createdAt: new Date()
    });
  }
  
  // 获取所有用户
  async getUsers(): Promise<User[]> {
    return await this.db.users.toArray();
  }
  
  // 获取单个用户
  async getUser(id: number): Promise<User | undefined> {
    return await this.db.users.get(id);
  }
  
  // 更新用户
  async updateUser(id: number, changes: Partial<User>): Promise<void> {
    await this.db.users.update(id, changes);
  }
  
  // 删除用户
  async deleteUser(id: number): Promise<void> {
    await this.db.users.delete(id);
  }
  
  // 按邮箱查找
  async findByEmail(email: string): Promise<User | undefined> {
    return await this.db.users.where('email').equals(email).first();
  }
}

五、缓存策略 #

5.1 缓存服务 #

typescript
// services/cache.service.ts
import { Injectable } from '@angular/core';
import { StorageService } from './storage.service';

interface CacheItem<T> {
  data: T;
  timestamp: number;
  expiry: number;
}

@Injectable({
  providedIn: 'root'
})
export class CacheService {
  private defaultExpiry = 5 * 60 * 1000; // 5分钟
  
  constructor(private storage: StorageService) {}
  
  async get<T>(key: string): Promise<T | null> {
    const item = await this.storage.get<CacheItem<T>>(key);
    
    if (!item) {
      return null;
    }
    
    // 检查是否过期
    if (Date.now() - item.timestamp > item.expiry) {
      await this.storage.remove(key);
      return null;
    }
    
    return item.data;
  }
  
  async set<T>(key: string, data: T, expiry: number = this.defaultExpiry): Promise<void> {
    const item: CacheItem<T> = {
      data,
      timestamp: Date.now(),
      expiry
    };
    
    await this.storage.set(key, item);
  }
  
  async remove(key: string): Promise<void> {
    await this.storage.remove(key);
  }
  
  async clear(): Promise<void> {
    await this.storage.clear();
  }
}

5.2 使用缓存 #

typescript
import { Component } from '@angular/core';
import { UserService } from './user.service';
import { CacheService } from './cache.service';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html'
})
export class HomePage {
  users: User[] = [];
  
  constructor(
    private userService: UserService,
    private cache: CacheService
  ) {}
  
  async loadUsers() {
    // 尝试从缓存获取
    const cached = await this.cache.get<User[]>('users');
    
    if (cached) {
      this.users = cached;
      return;
    }
    
    // 从API获取
    this.users = await this.userService.getUsers();
    
    // 存入缓存
    await this.cache.set('users', this.users, 10 * 60 * 1000);
  }
}

六、最佳实践 #

6.1 数据加密 #

typescript
import { Injectable } from '@angular/core';
import { StorageService } from './storage.service';

@Injectable({
  providedIn: 'root'
})
export class SecureStorageService {
  constructor(private storage: StorageService) {}
  
  async setSecure(key: string, value: any): Promise<void> {
    const encrypted = this.encrypt(JSON.stringify(value));
    await this.storage.set(key, encrypted);
  }
  
  async getSecure<T>(key: string): Promise<T | null> {
    const encrypted = await this.storage.get<string>(key);
    if (!encrypted) return null;
    
    const decrypted = this.decrypt(encrypted);
    return JSON.parse(decrypted);
  }
  
  private encrypt(data: string): string {
    // 实现加密逻辑
    return btoa(data);
  }
  
  private decrypt(data: string): string {
    // 实现解密逻辑
    return atob(data);
  }
}

6.2 数据迁移 #

typescript
// 数据版本管理
const DATA_VERSION = 2;

async migrateData() {
  const version = await this.storage.get<number>('data_version') || 0;
  
  if (version < 1) {
    // 迁移到版本1
    await this.migrateToV1();
  }
  
  if (version < 2) {
    // 迁移到版本2
    await this.migrateToV2();
  }
  
  await this.storage.set('data_version', DATA_VERSION);
}

七、总结 #

7.1 存储方案选择 #

场景 推荐方案
简单配置 Capacitor Storage
离线数据 SQLite
大量数据 IndexedDB
敏感数据 加密存储

7.2 下一步 #

掌握了本地存储后,接下来让我们学习 状态管理,了解Ionic的状态管理方案!

最后更新:2026-03-28