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

Web前端入门:JavaScript 一个简单的 IndexedDB 数据库入门示例

在前端风风雨雨的混了多年,从没在项目中实际使用过 IndexedDB 这个浏览器端的数据库,所以今天就摸了下 MDN 的后门,写一个简单的入门示例。

页面大概长这样:

85-1

源码:

以下代码包含了一个数据库所有的 CRUD (增删改查)操作。

<div><button id="js_add_btn">添加书籍</button>
</div>
<div><input type="text" name="" id="js_book_id" placeholder="输入书籍ID"/><button id="js_get_by_id_btn">查询书籍</button><button id="js_update_by_id_btn">更新书籍</button><button id="js_delete_by_id_btn">删除书籍</button>
</div>
<div><input type="text" name="" id="js_book_author" placeholder="输入书籍作者查询"/><button id="js_get_by_author_btn">查询书籍</button>
</div>
<div><button id="js_get_all_btn">查询所有书籍</button>
</div>
<div id="output"></div><script>(() => {// 数据库配置const dbName = 'MyDB';const storeName = 'books';const output = document.getElementById('output')let db = null;function setOutputContent(html) {output.innerText = html;}// 初始化数据库const initDB = () => {const request = indexedDB.open(dbName);// 数据库升级/创建时触发request.onupgradeneeded = (event) => {db = event.target.result;// 创建对象存储空间(类似数据库表)const store = db.createObjectStore(storeName, {keyPath: 'id', // 主键autoIncrement: true, // 自动生成ID});// 创建索引(允许通过作者查询)store.createIndex('author_idx', 'author', { unique: false });console.log('数据库已创建/升级');};// 数据库打开成功request.onsuccess = (event) => {db = event.target.result;console.log('数据库已打开');};// 数据库打开失败request.onerror = (event) => {console.error('数据库错误:', event.target.error);setOutputContent('数据库错误');};};// 封装包装函数,用于执行数据库相关方法function wrapper(func) {return new Promise((resolve, reject) => {const transaction = db.transaction([storeName], 'readwrite');const store = transaction.objectStore(storeName);const res = func(store)res.onsuccess = () => {resolve(res.result)};res.onerror = (event) => {reject(event.target.error)};});}// 添加数据const addBook = async (book) => {try {const result = await wrapper((store) => store.add(book))console.log(result);setOutputContent(`添加成功!书籍ID: ${result}`);} catch (error) {console.error(error);setOutputContent('添加失败');}};// 通过ID查询数据const getBook = async (id) => {try {const book = await wrapper((store) => store.get(id))if (book) {console.log('查询结果:', book);setOutputContent(`书名: ${book.title}\n作者: ${book.author}\n价格: $${book.price}`);} else {console.log('未找到书籍');setOutputContent('未找到该书籍');}} catch (error) {console.error(error);setOutputContent('查询失败');}};// 查询全部数据const getAllBook = async () => {try {const book = await wrapper((store) => store.getAll())if (book) {console.log('查询结果:', book);setOutputContent(`总数:${book.length}`);} else {console.log('未找到书籍');setOutputContent('未找到该书籍');}} catch (error) {console.error(error);setOutputContent('查询失败');}};// 更新数据--数据不存在时会添加数据const updateBook = async (book) => {try {const result = await wrapper((store) => store.put(book))console.log(result);setOutputContent(`更新成功!结果: ${result}`);} catch (error) {console.error(error);setOutputContent('更新失败');}};// 删除数据const deleteBook = async (id) => {try {const result = await wrapper((store) => store.delete(id))console.log(result);setOutputContent(`删除成功!结果: ${result}`);} catch (error) {console.error(error);setOutputContent('删除失败');}};// 根据作者查询const getByAuthor = async (author) => {try {const result = await wrapper((store) => {const index = store.index("author_idx");const request = index.getAll(author);return request;})console.log(result);setOutputContent(`查询成功!结果: ${JSON.stringify(result)}`);} catch (error) {console.error(error);setOutputContent('查询失败');}};// 添加书籍document.getElementById('js_add_btn').onclick = () => {addBook({title: 'Web前端入门',author: '前端路引',price: (0.99 * Math.random() + 10) .toFixed(2),});};// 根据ID查询document.getElementById('js_get_by_id_btn').onclick = () => {const bookId = document.getElementById('js_book_id').value;getBook(Number(bookId));};// 根据ID删除document.getElementById('js_delete_by_id_btn').onclick = () => {const bookId = document.getElementById('js_book_id').value;deleteBook(Number(bookId));};// 根据ID更新document.getElementById('js_update_by_id_btn').onclick = () => {const bookId = document.getElementById('js_book_id').value;updateBook({// 主键IDid: Number(bookId),title: 'Web前端入门',author: '公众号:前端路引',price: (0.99 * Math.random() + 10) .toFixed(2),});};// 根据作者查询document.getElementById('js_get_by_author_btn').onclick = () => {const author = document.getElementById('js_book_author').valuegetByAuthor(author);};// 查询全部document.getElementById('js_get_all_btn').onclick = () => {getAllBook();};// 页面加载时初始化数据库initDB();})();
</script>

IndexedDB 大小限制

以下内容为 AI 回答:

85-2

获取可用的存储空间大小

navigator.storage.estimate().then((estimate) => {console.log(`已使用:`,((estimate.usage / estimate.quota) * 100).toFixed(2));console.log(`可使用:`, (estimate.quota / 1024 / 1024).toFixed(2) + "MB");
});

写在最后

由于项目中很少使用,所以这 API 给不了太多建议~~

此 API 的应用场景还是有的,可以想想下那些超大文件在线处理应用,比如 ZIP、PSD、PPT 之类的文件,可以将文件解析后存在 IndexedDB 中,在需要的时候查询指定数据即可,这样可以节约很多的解析时间。

只是需要注意,所有存在浏览器端的数据,用户清空缓存之后都将不复存在,所以在使用时需做好容错处理~~

文章转载自:前端路引

原文链接:Web前端入门第 85 问:JavaScript 一个简单的 IndexedDB 数据库入门示例 - 前端路引 - 博客园

体验地址:JNPF快速开发平台

http://www.xdnf.cn/news/19105.html

相关文章:

  • 【开题答辩全过程】以 基于Vue Spring Boot的教师资格证考试助力系统设计与实现为例,包含答辩的问题和答案
  • QML Chart组件之坐标轴共有属性
  • AI人工智能系统搭建实战指南:常见陷阱与解决方案
  • 从零开始学习单片机17
  • PCIe 6.0的速度奥秘:数学视角下的编码革命与信号完整性突破
  • htb academy笔记-module-Penetration Testing Process(一)
  • Marin说PCB之POC电路layout设计仿真案例---11
  • 掌握 Linux 文件权限:chown 命令深度解析与实践
  • 【YOLO学习笔记】数据增强mosaic、Mixup、透视放射变换
  • LeetCode100-54螺旋矩阵
  • Edge浏览器新标签页加载慢
  • 零售行业全渠道应如何与零售后端系统集成?
  • Python 实战:内网渗透中的信息收集自动化脚本(5)
  • Rust项目的运行机制与实践
  • POE供电是什么?
  • 使用leapp升级Linux
  • 深入理解Go 与 PHP 在参数传递上的核心区别
  • 领域知识如何注入LLM-检索增强生成
  • Java 学习笔记(基础篇11)
  • ExcelJS实现导入转换HTML展示(附源码可直接使用)
  • JavaScript 基础核心知识点总结:从使用方式到核心语法
  • RAG 系统核心:深入理解向量相似度匹配与文本向量化
  • Springboot高校迎新系统2cbcd(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • 【原创】MiniCPM-V 4.5模型测试 pk gemini2.5pro 本地8G显卡
  • 第四章 Vue3 + Three.js 实战:GLTF 模型加载与交互完整方案
  • @Gitea 介绍部署使用详细指南
  • 【二叉树(DFS)- LeetCode】124. 二叉树中的最大路径和
  • 3 反向传播
  • WebStorm-在WebStorm中使用Git管理项目
  • Set和Map