当前位置: 首页 > article >正文

angular使用IndexedDb实现增删改查sql

说明:我听说前端有一款数据库,叫IndexedDb数据库,可以存储超大的文件和数据,大约有250M,有了这个,就可以在浏览器里面,存储超大的数据,
事实上IndexedDb存储的数据,存在浏览器文件夹的c盘,缓存浏览器的文件夹里面,只要你存了数据,用户关闭浏览器,再次打开,数据依然还在,可以加载,用来做缓存,非常方便
因此,我就计划用angular框架,使用indexdb技术,先写一个简单的增删改查的小demo,用来存储用户信息,弄了一上午,总算可以用了,下面是详细步骤和效果图

效果图:
在这里插入图片描述

step0:用npm安装IndexedDb

npm install ngx-indexed-db 

step1:IndexedDb安装成功后,在 package.json可以查看安装的IndexedDb版本19.3.3

 "@angular/animations": "^19.1.0",
    "@angular/cdk": "^19.1.5",
    "@angular/common": "^19.1.0",
    "@angular/compiler": "^19.1.0",
    "@angular/core": "^19.1.0",
    "@angular/forms": "^19.1.0",
    "@angular/material": "^19.1.5",
    "@angular/platform-browser": "^19.1.0",
    "@angular/platform-browser-dynamic": "^19.1.0",
    "@angular/router": "^19.1.0",
    "ngx-indexed-db": "^19.3.3",
    "rxjs": "~7.8.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.15.0"

step2:接下来需要在angular项目中,导入IndexedDb
新建一个文件,文件名和具体路径是:C:\Users\Administrator\WebstormProjects\untitled4\src\app\db.config.ts

import { DBConfig } from 'ngx-indexed-db';

export const DB_CONFIG: DBConfig = {
  name: 'Angular19DB',
  version: 2,
  objectStoresMeta: [{
    store: 'tasks',
    storeConfig: {
      keyPath: 'id',
      autoIncrement: true
    },
    storeSchema: [
      { name: 'title', keypath: 'title', options: { unique: false } },
      { name: 'status', keypath: 'status', options: { unique: false } }
    ]
  }]
};

step3:然后就是注册,
文件名和具体路径是:C:\Users\Administrator\WebstormProjects\untitled4\src\app\app.config.ts

import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';
import { provideIndexedDb } from 'ngx-indexed-db';
import { DB_CONFIG } from './db.config';

import { provideAnimations } from '@angular/platform-browser/animations';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';



export const appConfig: ApplicationConfig = {
  providers: [provideIndexedDb(DB_CONFIG),provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes),provideAnimations(), provideAnimationsAsync()]
};

step4:路由这些,不用我多说了吧,新建一个模块,添加到路由里面,然后就直接开整,

 ng generate component student

step5:C:\Users\Administrator\WebstormProjects\untitled4\src\app\student\student.component.ts

import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
import { DatabaseService } from './data.service';
import { FormsModule } from '@angular/forms';
import { NgForOf } from '@angular/common';
import { Task } from './task.model';// 从统一定义文件导入

@Component({
  selector: 'app-task',
  imports: [FormsModule, NgForOf],
  templateUrl: './student.component.html',
  styleUrl: './student.component.css'
})

export class StudentComponent  implements OnInit {
  tasks: Task[] = [];
  newTask: Omit<Task, 'id'> = {
    title: '',
    status: 'pending'
  };

  constructor(
    private db: DatabaseService,
    private cdr: ChangeDetectorRef
  ) {}

  async ngOnInit() {
    await this.loadTasks();
  }

  async loadTasks() {
    // 添加类型断言确保数据一致性
    this.tasks = await this.db.getAllTasks() as Task[];
    this.cdr.detectChanges();
  }

  async addTask() {
    if (this.newTask.title.trim()) {
      // 类型安全传递
      await this.db.addTask(this.newTask);
      this.newTask = { title: '', status: 'pending' };
      await this.loadTasks();
    }
  }

  async updateTask(task: Task) {
    // 添加空值检查
    if (task.id === undefined) return;

    await this.db.updateTask(task);
    await this.loadTasks();
  }

  async deleteTask(id: number) {
    await this.db.deleteTask(id);
    await this.loadTasks();
  }
}

step6:C:\Users\Administrator\WebstormProjects\untitled4\src\app\student\task.model.ts

// src/app/models/task.model.ts
export interface Task {
  id?: number;  // 将id改为可选属性
  title: string;
  status: 'pending' | 'completed';
}

step7:C:\Users\Administrator\WebstormProjects\untitled4\src\app\student\data.service.ts

import { Injectable } from '@angular/core';
import { Task } from './task.model';

@Injectable({ providedIn: 'root' })
export class DatabaseService {
  private db!: IDBDatabase;
  private readonly dbName = 'AngularDB';
  private readonly storeName = 'tasks';

  // 添加数据库准备状态追踪
  private dbReady: Promise<void>;

  constructor() {
    this.dbReady = this.initializeDB();
  }

  private async initializeDB(): Promise<void> {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open(this.dbName, 1);

      request.onupgradeneeded = (event) => {
        this.db = (event.target as IDBOpenDBRequest).result;
        if (!this.db.objectStoreNames.contains(this.storeName)) {
          const store = this.db.createObjectStore(this.storeName, {
            keyPath: 'id',
            autoIncrement: true
          });
          store.createIndex('title', 'title', { unique: false });
        }
      };

      request.onsuccess = (event) => {
        this.db = (event.target as IDBOpenDBRequest).result;
        resolve();
      };

      request.onerror = (event) => {
        reject((event.target as IDBRequest).error);
      };
    });
  }

  // 所有方法添加等待初始化
  async getAllTasks(): Promise<Task[]> {
    await this.dbReady;
    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction(this.storeName, 'readonly');
      const store = transaction.objectStore(this.storeName);
      const request = store.getAll();

      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error);
    });
  }

  async addTask(task: Omit<Task, 'id'>): Promise<number> {
    await this.dbReady;
    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction(this.storeName, 'readwrite');
      const store = transaction.objectStore(this.storeName);
      const request = store.add(task);

      request.onsuccess = () => resolve(request.result as number);
      request.onerror = () => reject(request.error);
    });
  }

  async updateTask(task: Task): Promise<void> {
    await this.dbReady;
    if (task.id === undefined) {
      throw new Error('Cannot update task without ID');
    }

    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction(this.storeName, 'readwrite');
      const store = transaction.objectStore(this.storeName);
      const request = store.put(task);

      request.onsuccess = () => resolve();
      request.onerror = () => reject(request.error);
    });
  }

  async deleteTask(id: number): Promise<void> {
    await this.dbReady;
    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction(this.storeName, 'readwrite');
      const store = transaction.objectStore(this.storeName);
      const request = store.delete(id);

      request.onsuccess = () => resolve();
      request.onerror = () => reject(request.error);
    });
  }
}

step8:C:\Users\Administrator\WebstormProjects\untitled4\src\app\student\student.component.html

<div class="task-manager">
  <div class="task-header">
    <input
      [(ngModel)]="newTask.title"
      placeholder="Enter task title"
      class="task-input"
      (keyup.enter)="addTask()"
    >
    <button
      class="primary-btn"
      (click)="addTask()"
    >
      + Add Task
    </button>
  </div>

  <div class="task-list">
    <div *ngFor="let task of tasks" class="task-item">
      <input
        [(ngModel)]="task.title"
        class="task-input"
      >
      <select
        [(ngModel)]="task.status"
        (change)="updateTask(task)"
        class="status-select"
      >
        <option value="pending">⏳ Pending</option>
        <option value="completed">✅ Completed</option>
      </select>
      <button
        class="danger-btn"
        (click)="deleteTask(task.id!)"
      >
        🗑 Delete
      </button>
    </div>
  </div>
</div>

step9:C:\Users\Administrator\WebstormProjects\untitled4\src\app\student\student.component.css

/* 现代配色方案 */
.task-manager {
  max-width: 800px;
  margin: 2rem auto;
  padding: 2rem;
  background: white;
  border-radius: 12px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.05);
}

.task-header {
  display: flex;
  gap: 1rem;
  margin-bottom: 2rem;
}

.task-input {
  flex: 1;
  padding: 12px;
  border: 2px solid #e9ecef;
  border-radius: 8px;
  font-size: 16px;
  transition: border-color 0.3s ease;
}
.task-input:focus {
  outline: none;
  border-color: #4a90e2;
  box-shadow: 0 0 0 3px rgba(74, 144, 226, 0.1);
}

.primary-btn {
  padding: 10px 20px;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  font-weight: 500;
  transition: all 0.3s ease;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: linear-gradient(135deg, #4a90e2 0%, #2d7ff9 100%);
  color: white;
}
.primary-btn:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  background: linear-gradient(135deg, #3d85d6 0%, #2770e0 100%);
}
.primary-btn:active {
  transform: translateY(0);
}

.danger-btn {
  padding: 10px 20px;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  font-weight: 500;
  transition: all 0.3s ease;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: linear-gradient(135deg, #ff4757 0%, #ff6b81 100%);
  color: white;
}
.danger-btn:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.danger-btn:active {
  transform: translateY(0);
}

.task-list {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.task-item {
  display: flex;
  gap: 1rem;
  align-items: center;
  padding: 1.5rem;
  background: #f8f9fa;
  border-radius: 8px;
  transition: transform 0.3s ease;
}
.task-item:hover {
  transform: translateX(5px);
}

.status-select {
  padding: 8px 12px;
  border: 2px solid #e9ecef;
  border-radius: 6px;
  background: white;
  cursor: pointer;
  transition: all 0.3s ease;
}
.status-select:focus {
  outline: none;
  border-color: #4a90e2;
}

直接点击运行,然后success

end


http://www.kler.cn/a/563144.html

相关文章:

  • 【实战中提升自己】防火墙篇之双ISP切换与VRRP切换对于用户的体验
  • Sublime Text4安装、汉化
  • 每日一题——字母异位词分组
  • 刚充值Deepseek账号,但接入官方的API却遇到了问题【VSCode Cline Cursor Deepseek deepseek-reasoner】
  • Uniapp 小程序:语音播放与暂停功能的实现及优化方案
  • Flink Checkpoint机制详解
  • 数据存储:一文掌握存储数据到MongoDB详解
  • DS-3KM220250226 3K引擎修复版传奇2025版完整源码搭建教程
  • JAVA面试_进阶部分_Linux面试题
  • 【Uniapp-Vue3】登录成功后获取当前用户信息并渲染到页面中
  • JDBC连接池
  • jar生产部署脚本
  • 使用ZFile打造属于自己的私有云系统结合内网穿透实现安全远程访问
  • OpenHarmony DFX子系统
  • seasms v9 注入漏洞 + order by注入+​information_schema​解决方法
  • Gtest, Junit,以及pytest对比理解
  • 轻量化网络设计|ShuffleNet:深度学习中的轻量化革命
  • 嵌入式的应用领域和发展趋势
  • 什么是Sass,如何使用?
  • Game Maker 0.11更新:构建社交竞速游戏并增强玩家互动