You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript中使用Dexie的Version.upgrade()升级并填充数据表

用Dexie.js的Version.upgrade()在TypeScript中升级并填充数据表

嘿,我来帮你搞定这个Dexie版本升级和数据填充的事儿!你已经基于官方TS示例扩展了代码,接下来咱们把Version.upgrade()的逻辑加进去,一步步来:

第一步:补全接口与数据库类定义

首先先把你提到的ICity和其他接口补全,然后在AppDatabase里定义版本规则和升级逻辑:

export interface ICity {
  id?: number;
  name: string;
}

// 补全你示例中提到的其他接口,避免代码报错
export interface IContact {
  id?: number;
  name: string;
}

export interface IEmailAddress {
  id?: number;
  contactId: number;
  email: string;
}

export interface IPhoneNumber {
  id?: number;
  contactId: number;
  number: string;
}

export class AppDatabase extends Dexie {
  contacts: Dexie.Table<IContact, number>;
  emails: Dexie.Table<IEmailAddress, number>;
  phones: Dexie.Table<IPhoneNumber, number>;
  cities: Dexie.Table<ICity, number>; // 新增的城市表

  constructor() {
    super('AppDatabase');

    // 版本1:初始表结构(对应你原来的contacts、emails、phones表)
    this.version(1).stores({
      contacts: '++id, name',
      emails: '++id, contactId, email',
      phones: '++id, contactId, number'
    });

    // 版本2:新增cities表,同时在升级时填充初始数据
    this.version(2).stores({
      cities: '++id, name' // 只需要定义新增/变更的表结构
    }).upgrade(async (tx) => {
      // 这里就是升级时的逻辑,咱们批量插入一些城市数据
      const initialCities: ICity[] = [
        { name: '北京' },
        { name: '上海' },
        { name: '广州' },
        { name: '深圳' }
      ];
      // 注意要用tx.table()操作表,因为升级是在事务上下文里执行的
      await tx.table('cities').bulkAdd(initialCities);
      console.log('城市表创建并填充完成!');
    });

    // 把表绑定到类的属性上,方便后续调用
    this.contacts = this.table('contacts');
    this.emails = this.table('emails');
    this.phones = this.table('phones');
    this.cities = this.table('cities');
  }
}

第二步:搞懂升级逻辑的核心点

  • 版本号必须递增:每次修改数据库结构或者需要填充数据,都得把版本号往上加,不能回退版本号,Dexie靠版本号判断是否需要执行升级逻辑。
  • stores()只写变更:不用重复写旧版本已经定义过的表,Dexie会自动保留之前的表结构,只处理你在新版本里声明的表变更。
  • upgrade()是异步的:一定要用async/await或者返回Promise,不然Dexie可能会在数据没填充完就结束升级,导致数据丢失。

第三步:测试升级后的数据库

接下来就可以正常使用这个数据库了,比如测试下城市数据有没有被成功填充:

const db = new AppDatabase();

// 读取所有城市数据
db.cities.toArray().then(cities => {
  console.log('数据库里的城市:', cities);
}).catch(err => {
  console.error('读取城市数据出错:', err);
});

额外小提示

  • 如果是要修改现有表的结构(比如给contacts表加个age字段),也要在对应版本的stores()里更新,然后在upgrade()里给旧数据补值,比如:
    this.version(3).stores({
      contacts: '++id, name, age' // 新增age索引
    }).upgrade(async (tx) => {
      // 给旧的contact数据默认设置age为30
      const contacts = await tx.table('contacts').toArray();
      await Promise.all(contacts.map(contact => 
        tx.table('contacts').update(contact.id!, { age: 30 })
      ));
    });
    
  • 如果是第一次创建数据库就要填充初始数据,别用upgrade(),用populate事件更合适,比如:
    this.on('populate', async () => {
      // 只有数据库第一次创建时才会触发这个事件
      await db.contacts.bulkAdd([
        { name: '张三' },
        { name: '李四' }
      ]);
    });
    

内容的提问来源于stack exchange,提问作者kabeleced

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:57:21