18_HTML5 Web IndexedDB 数据库 --[HTML5 API 学习之旅]

HTML5 Web IndexedDB API 是一种在用户浏览器中存储大量结构化数据的机制,它允许存储和检索键值对,其中键可以是任何有效的JavaScript对象。IndexedDB 主要用于需要复杂查询的数据密集型Web应用。

IndexedDB 的特点:

HTML5 Web IndexedDB API 是一种强大的客户端存储解决方案,它允许Web应用程序在用户的浏览器中存储大量的结构化数据。IndexedDB 的特点如下:

  1. 异步操作

    • 所有的数据库操作都是异步的,这意味着它们不会阻塞用户界面或其他脚本执行。这有助于保持网页的响应性。
  2. 键值对存储

    • 数据以对象的形式存储,每个对象与一个主键相关联。主键可以是任何有效的JavaScript对象(如字符串、数字等),也可以是由开发者定义的自动生成的ID。
  3. 事务支持

    • IndexedDB 使用事务来保证数据的一致性和完整性。事务提供了读取、写入和只读三种模式,并且确保了所有操作要么全部成功要么全部失败。
  4. 索引能力

    • 除了主键外,还可以为对象存储创建多个索引,以加速基于非主键字段的数据检索。这些索引使得复杂查询成为可能,比如查找特定范围内的记录或者按照某个属性排序。
  5. 版本控制系统

    • 每个数据库都有一个版本号,当需要修改数据库结构时(例如添加新的对象存储或索引),可以通过升级数据库版本来实现。upgradeneeded 事件会在首次打开数据库或请求更高版本时触发,以便进行必要的更改。
  6. 丰富的API

    • 提供了一系列的方法用于管理数据库、对象存储、索引以及执行CRUD(创建、读取、更新、删除)操作。API设计直观,易于使用。
  7. 大容量存储

    • IndexedDB 支持比本地存储(LocalStorage)更大的数据量,具体大小取决于用户设置和浏览器实现。理论上它可以存储数GB的数据。
  8. 持久化存储

    • 存储在 IndexedDB 中的数据是持久性的,除非被明确地删除或用户清空浏览器缓存,否则数据会一直保存。
  9. 跨域限制

    • IndexedDB 遵循同源策略(Same-origin policy),意味着只有来自相同源(协议、域名、端口)的页面才能访问同一个 IndexedDB 数据库。
  10. 事件驱动架构

    • IndexedDB 使用事件模型来进行错误处理和完成通知。例如,在尝试打开数据库或执行事务时发生的事件可以用来控制流程和响应结果。

通过这些特性,IndexedDB 成为了构建离线Web应用、增强用户体验和性能的一个重要工具。然而,由于其复杂性相对较高,对于简单的数据存储需求,可能会选择更简单的方案如 LocalStorage 或 SessionStorage。

基本使用步骤:

使用 HTML5 Web IndexedDB API 进行基本操作的步骤可以分为以下几个关键阶段:

1. 打开数据库

首先,你需要尝试打开一个已有的数据库或者创建一个新的数据库。这通过 indexedDB.open() 方法完成,该方法接受两个参数:数据库名称和版本号。

var request = indexedDB.open("MyDatabase", 1);

2. 处理升级需求(如果需要)

当首次创建数据库或数据库版本增加时,会触发 upgradeneeded 事件。在这个事件处理函数中,你可以定义数据库结构,包括创建对象存储空间和索引。

request.onupgradeneeded = function(event) {
    var db = event.target.result;
    // 创建一个名为 "contacts" 的对象存储空间,设置 "id" 作为主键
    var objectStore = db.createObjectStore("contacts", { keyPath: "id", autoIncrement: true });
    // 可选地,在对象存储上创建索引
    objectStore.createIndex("nameIndex", "name", { unique: false });
};

3. 监听成功和错误事件

为了知道何时数据库已经成功打开以及是否有任何错误发生,你应该添加 onsuccessonerror 事件监听器。

request.onsuccess = function(event) {
    console.log("数据库打开成功");
    db = event.target.result; // 保存对数据库的引用
};

request.onerror = function(event) {
    console.error("数据库打开失败");
};

4. 开始事务

在进行任何数据操作之前,你必须开始一个事务。事务指定了要访问的对象存储空间列表,并声明了事务类型(只读 "readonly" 或读写 "readwrite")。

var transaction = db.transaction(["contacts"], "readwrite");

5. 获取对象存储

从事务中获取你要操作的对象存储空间。

var objectStore = transaction.objectStore("contacts");

6. 操作数据

根据你的需求,使用适当的方法来添加、获取、更新或删除数据。

  • 添加/更新:使用 add()put() 方法。
  • 获取:使用 get() 方法。
  • 删除:使用 delete() 方法。
  • 遍历:使用游标(cursor)遍历对象存储中的记录。
// 添加一条新记录到对象存储中
var addRequest = objectStore.add({ name: "张三", email: "zhangsan@example.com" });

addRequest.onsuccess = function(event) {
    console.log("记录添加成功,ID:", event.target.result);
};

// 获取指定 ID 的记录
var getRequest = objectStore.get(1);

getRequest.onsuccess = function(event) {
    if (event.target.result) {
        console.log("找到记录:", event.target.result);
    } else {
        console.log("未找到记录");
    }
};

7. 监听事务完成

监听事务的 complete 事件以确认所有操作都已完成。

transaction.oncomplete = function() {
    console.log("事务已完成");
};

8. 关闭数据库连接

当你不再需要与数据库交互时,应该关闭数据库连接以释放资源。

db.close();

以上是使用 IndexedDB 的基本流程。根据实际应用的需求,可能还需要更复杂的逻辑和错误处理。记住,IndexedDB 是异步工作的,所以通常你会用回调函数、Promise 或者 async/await 来管理这些异步操作。

示例代码

以下是六个使用 HTML5 Web IndexedDB 的示例,每个示例都展示了不同的功能和用法:

示例 1: 创建数据库和对象存储

// 尝试打开名为 "MyDatabase" 的数据库,如果不存在则创建之,版本号为 1。
var request = indexedDB.open("MyDatabase", 1);

// 当需要升级数据库时触发此事件(首次创建或版本号增加)。
request.onupgradeneeded = function(event) {
    // 获取数据库实例
    var db = event.target.result;

    // 创建一个名为 "books" 的对象存储空间,并指定 "isbn" 作为主键。
    // 每个存储在 "books" 中的对象都必须有一个名为 "isbn" 的属性作为其唯一标识符。
    var objectStore = db.createObjectStore("books", { keyPath: "isbn" });

    // 可选地,在这里可以为 "books" 对象存储创建索引,以加速特定字段的查询。
    // 例如:objectStore.createIndex("titleIndex", "title", { unique: false });
};

// 数据库成功打开时触发此事件。
request.onsuccess = function(event) {
    // 保存对数据库连接的引用(在这个简单的例子中未使用)
    var db = event.target.result;

    // 输出确认信息到控制台,表示数据库已经成功打开。
    console.log("数据库已成功打开");

    // 注意:在此之后,你通常会开始进行事务操作(如添加、读取、更新或删除数据)。
};

// 如果打开数据库过程中出现错误,则触发此事件。
request.onerror = function(event) {
    // 打印错误信息到控制台,帮助调试问题。
    console.error("数据库打开失败");
};

在这里插入图片描述

示例 2: 向对象存储中添加记录

function addBook(db, book) {
    // 开始一个新事务,指定要访问的对象存储空间("books"),并设置为读写模式 ("readwrite")。
    var transaction = db.transaction(["books"], "readwrite");

    // 从当前事务中获取名为 "books" 的对象存储空间实例。
    var objectStore = transaction.objectStore("books");

    // 向对象存储空间中添加一个新的书本记录。如果主键(这里是指定的 "isbn" 字段)已经存在,则会抛出错误。
    var addRequest = objectStore.add(book);

    // 当添加操作成功完成时触发此事件处理程序。
    addRequest.onsuccess = function(event) {
        // 输出确认信息到控制台,表示书本已成功添加。
        console.log("书本添加成功");
    };

    // 当整个事务完成时触发此事件处理程序,无论是否有任何操作失败。
    transaction.oncomplete = function() {
        // 输出信息到控制台,表示所有事务内的操作已完成。
        console.log("事务完成");
    };

    // 如果事务中的任何一个操作发生错误,则触发此事件处理程序。
    transaction.onerror = function(event) {
        // 输出错误信息到控制台,帮助调试问题。
        console.error("添加失败");
    };
}

// 使用方法:尝试向数据库中添加一本书。
// 注意:这里的 "db" 参数应该是由 indexedDB.open 成功返回的数据库连接对象,而不是字符串 "MyDatabase"。
// 正确的做法是先打开数据库,然后使用返回的数据库连接对象调用 addBook 函数。
var request = indexedDB.open("MyDatabase", 1);

request.onsuccess = function(event) {
    // 获取数据库连接
    var db = event.target.result;

    // 现在可以安全地调用 addBook 函数,并传递实际的数据库连接对象。
    addBook(db, { isbn: '123456789', title: 'HTML5入门' });
    // addBook(db, { isbn: '12345', title: 'go入门' });

    // 关闭数据库连接(通常在所有操作完成后进行)
    // db.close();
};

request.onerror = function(event) {
    console.error("数据库打开失败");
};

在这里插入图片描述

示例 3: 查询特定记录

function getBook(db, isbn) {
    // 开始一个新事务,指定要访问的对象存储空间("books"),并设置为只读模式 ("readonly")。
    // 由于我们只是查询数据而不会修改它,所以使用 "readonly" 是合适的。
    var transaction = db.transaction(["books"], "readonly");

    // 从当前事务中获取名为 "books" 的对象存储空间实例。
    var objectStore = transaction.objectStore("books");

    // 尝试根据提供的 ISBN 获取书本记录。
    var getRequest = objectStore.get(isbn);

    // 当获取操作成功完成时触发此事件处理程序。
    getRequest.onsuccess = function(event) {
        // 检查是否找到了匹配的书本记录。
        if (event.target.result) {
            // 如果找到,输出书本信息到控制台。
            console.log("找到的书本:", event.target.result);
        } else {
            // 如果没有找到对应的 ISBN,输出未找到的信息。
            console.log("未找到该ISBN的书本");
        }
    };

    // 注意:对于只读事务,通常不需要监听 oncomplete 或 onerror 事件,
    // 因为这些事件主要用于确保所有写入操作都已成功完成或用于错误处理。
}

// 使用方法:尝试从数据库中获取一本书。
// 注意:这里的 "db" 参数应该是由 indexedDB.open 成功返回的数据库连接对象,而不是字符串 "MyDatabase"。
// 正确的做法是先打开数据库,然后使用返回的数据库连接对象调用 getBook 函数。
var request = indexedDB.open("MyDatabase", 1);

request.onsuccess = function(event) {
    // 获取数据库连接
    var db = event.target.result;

    // 现在可以安全地调用 getBook 函数,并传递实际的数据库连接对象。
    getBook(db, '123456789');

    // 关闭数据库连接(通常在所有操作完成后进行)
    // db.close();
};

request.onerror = function(event) {
    console.error("数据库打开失败");
};

在这里插入图片描述

示例 4: 更新现有记录

function updateBook(db, updatedBook) {
    // 开始一个新事务,指定要访问的对象存储空间("books"),并设置为读写模式 ("readwrite")。
    // 由于我们打算修改数据,因此需要使用 "readwrite" 模式以允许对数据库进行更改。
    var transaction = db.transaction(["books"], "readwrite");

    // 从当前事务中获取名为 "books" 的对象存储空间实例。
    var objectStore = transaction.objectStore("books");

    // 使用 put() 方法更新或插入书本记录。
    // 如果对象存储中已存在具有相同主键(这里是指定的 "isbn" 字段)的记录,则该记录会被更新;
    // 如果不存在这样的记录,则会创建一条新的记录。
    var putRequest = objectStore.put(updatedBook);

    // 当 put() 操作成功完成时触发此事件处理程序。
    putRequest.onsuccess = function(event) {
        // 输出确认信息到控制台,表示书本已成功更新。
        console.log("书本更新成功");
    };

    // 当整个事务完成时触发此事件处理程序,无论是否有任何操作失败。
    transaction.oncomplete = function() {
        // 输出信息到控制台,表示所有事务内的操作已完成。
        console.log("事务完成");
    };

    // 如果事务中的任何一个操作发生错误,则触发此事件处理程序。
    transaction.onerror = function(event) {
        // 输出错误信息到控制台,帮助调试问题。
        console.error("更新失败");
    };
}

// 使用方法:尝试更新数据库中的一本书。
// 注意:这里的 "db" 参数应该是由 indexedDB.open 成功返回的数据库连接对象,而不是字符串 "MyDatabase"。
// 正确的做法是先打开数据库,然后使用返回的数据库连接对象调用 updateBook 函数。
var request = indexedDB.open("MyDatabase", 1);

request.onsuccess = function(event) {
    // 获取数据库连接
    var db = event.target.result;

    // 现在可以安全地调用 updateBook 函数,并传递实际的数据库连接对象。
    updateBook(db, { isbn: '123456789', title: 'HTML5进阶' });

    // 关闭数据库连接(通常在所有操作完成后进行)
    // db.close();
};

request.onerror = function(event) {
    console.error("数据库打开失败");
};

在这里插入图片描述

示例 5: 删除记录

function deleteBook(db, isbn) {
    // 开始一个新事务,指定要访问的对象存储空间("books"),并设置为读写模式 ("readwrite")。
    // 由于我们打算删除数据,因此需要使用 "readwrite" 模式以允许对数据库进行更改。
    var transaction = db.transaction(["books"], "readwrite");

    // 从当前事务中获取名为 "books" 的对象存储空间实例。
    var objectStore = transaction.objectStore("books");

    // 使用 delete() 方法尝试根据提供的 ISBN 删除书本记录。
    // 如果对象存储中存在具有相同主键(这里是指定的 "isbn" 字段)的记录,则该记录会被删除;
    // 如果不存在这样的记录,则不会有任何操作执行,但也不会抛出错误。
    var deleteRequest = objectStore.delete(isbn);

    // 当 delete() 操作成功完成时触发此事件处理程序。
    // 注意:即使没有找到对应的记录,onsuccess 也会被触发,因为 delete() 成功意味着请求本身已成功执行。
    deleteRequest.onsuccess = function(event) {
        // 输出确认信息到控制台,表示书本已成功删除。
        console.log("书本删除成功");
    };

    // 当整个事务完成时触发此事件处理程序,无论是否有任何操作失败。
    // 这是确保所有操作都已完成的最后一个检查点。
    transaction.oncomplete = function() {
        // 输出信息到控制台,表示所有事务内的操作已完成。
        console.log("事务完成");
    };

    // 如果事务中的任何一个操作发生错误,则触发此事件处理程序。
    // 错误可能由多种原因引起,如违反约束、网络问题等。
    transaction.onerror = function(event) {
        // 输出错误信息到控制台,帮助调试问题。
        console.error("删除失败", event.target.error);
    };
}

// 使用方法:尝试从数据库中删除一本书。
// 注意:这里的 "db" 参数应该是由 indexedDB.open 成功返回的数据库连接对象,而不是字符串 "MyDatabase"。
// 正确的做法是先打开数据库,然后使用返回的数据库连接对象调用 deleteBook 函数。
var request = indexedDB.open("MyDatabase", 1);

request.onsuccess = function(event) {
    // 获取数据库连接
    var db = event.target.result;

    // 现在可以安全地调用 deleteBook 函数,并传递实际的数据库连接对象。
    deleteBook(db, '123456789');

    // 关闭数据库连接(通常在所有操作完成后进行)
    // db.close();
};

request.onerror = function(event) {
    // 如果打开数据库过程中出现错误,则输出错误信息。
    console.error("数据库打开失败", event.target.error);
};

在这里插入图片描述

示例 6: 遍历所有记录

function listAllBooks(db) {
    // 开始一个新事务,指定要访问的对象存储空间("books"),并设置为只读模式 ("readonly")。
    // 由于我们只是遍历数据而不会修改它,所以使用 "readonly" 是合适的。
    var transaction = db.transaction(["books"], "readonly");

    // 从当前事务中获取名为 "books" 的对象存储空间实例。
    var objectStore = transaction.objectStore("books");

    // 使用 openCursor() 方法创建一个游标来遍历对象存储中的所有记录。
    // 游标允许我们逐条访问对象存储中的记录。
    objectStore.openCursor().onsuccess = function(event) {
        // 获取游标对象
        var cursor = event.target.result;

        if (cursor) {
            // 如果存在当前记录,则输出书本信息到控制台。
            console.log("书名:", cursor.value.title, ", ISBN:", cursor.value.isbn);

            // 继续移动游标到下一个记录。
            cursor.continue();
        } else {
            // 如果没有更多记录,输出遍历完毕的信息。
            console.log("遍历完毕");
        }
    };
}

// 使用方法:尝试列出数据库中的所有书籍。
// 注意:这里的 "db" 参数应该是由 indexedDB.open 成功返回的数据库连接对象,而不是字符串 "MyDatabase"。
// 正确的做法是先打开数据库,然后使用返回的数据库连接对象调用 listAllBooks 函数。
var request = indexedDB.open("MyDatabase", 1);

request.onsuccess = function(event) {
    // 获取数据库连接
    var db = event.target.result;

    // 现在可以安全地调用 listAllBooks 函数,并传递实际的数据库连接对象。
    listAllBooks(db);

    // 关闭数据库连接(通常在所有操作完成后进行)
    // db.close();
};

request.onerror = function(event) {
    // 如果打开数据库过程中出现错误,则输出错误信息。
    console.error("数据库打开失败", event.target.error);
};

在这里插入图片描述

这些示例涵盖了创建数据库、插入数据、查询、更新、删除以及遍历所有记录的基本操作。你可以根据自己的需要调整这些代码片段,以适应更复杂的应用场景。请注意,为了使上述代码正常工作,你需要在适当的位置保存 db 变量(即从 indexedDB.open()onsuccess 回调函数中获取到的数据库连接)。

测试代码下载

html5_api代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/944218.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Seata】分布式事务问题和理论基础

目录 1.分布式事务问题 1.1本地事务 1.2分布式事务 2.理论基础 2.1CAP定理 2.1.1一致性 2.1.2可用性 2.1.3分区容错 2.1.4矛盾 2.2BASE理论 2.3解决分布式事务的思路 1.分布式事务问题 1.1本地事务 本地事务,也就是传统的单机事务。在传统数据库事务中…

【数据库初阶】Linux中库的基础操作

🎉博主首页: 有趣的中国人 🎉专栏首页: 数据库初阶 🎉其它专栏: C初阶 | C进阶 | 初阶数据结构 亲爱的小伙伴们,大家好!在这篇文章中,我们将深入浅出地为大家讲解 Linux…

数据结构与算法Python版 图

文章目录 一、图二、抽象数据类型图三、图的实现-邻接列表法 一、图 表示图的英文单词 painting:用画刷画的油画drawing:用硬笔画的素描/线条画picture:真实形象所反映的画,如照片等,如take pictureimage&#xff1a…

Word表格另起一页解决办法

Word表格另起一页解决办法 表格设置根据内容自动调整,取消指定高度第1步 第2步

Python数据可视化案例——折线图

目录 json介绍: Pyecharts介绍 安装pyecharts包? 构建一个基础的折线图 配置全局配置项 综合案例: 使用工具对数据进行查看?: 数据处理 json介绍: json是一种轻量级的数据交互格式,采用完全独立于编程语言的…

【Seata】seata的部署和集成

一、部署Seata的tc-server 1.下载 首先我们要下载seata-server包,地址在http://seata.io/zh-cn/blog/download.html 当然,课前资料也准备好了: 2.解压 在非中文目录解压缩这个zip包,其目录结构如下: 3.修改配置 修…

链表 之 无头结点【哨兵位】单向非循环链表【单链表】增删改查 等方法

系列文章目录 🎈 🎈 我的CSDN主页:OTWOL的主页,欢迎!!!👋🏼👋🏼 🎉🎉我的C语言初阶合集:C语言初阶合集,希望能…

GCP Cloud Architect exam - PASS

备考指南 推荐视频课程 https://www.udemy.com/course/google-cloud-architect-certifications/?couponCodeKEEPLEARNING 推荐题库 https://www.udemy.com/course/gcp-professional-cloud-architect-exam-practice-tests-2024​/?couponCodeKEEPLEARNING 错题集 http…

CCF-GESP 等级考试 2023年12月认证C++二级真题解析

2023年12月真题 一、单选题(每题2分,共30分) 正确答案:C 考察知识点:变量的定义与使用 解析:变量命名规则:1、只能包括数字、字母和下划线;2、不能以数字开头;3、不能和…

5.学习webpack配置 babel基本配置

babel是一个javascript编译工具,其主要功能是将新版本的JavaScript代码(如es6)转换为旧版本的代码(如es5),以便能够在旧版本的浏览器或环境中运行。一般配合webpack使用。 使用npm i -D babel/core babel/p…

配置搜索无人机

升级ubuntu内核 https://www.bilibili.com/video/BV11X4y1h7qN/?spm_id_from333.337.search-card.all.click 进入四个内核文件并安装 sudo dpkg -i *.deb安装ROS,PX4,XTDrone,QGC https://blog.csdn.net/qq_45493236/article/details/13…

Linux内核蓝牙子系统有什么(9)

接前一篇文章:Linux内核蓝牙子系统有什么(8) 本文内容参考: Linux之蓝牙相关代码浅析 | DDNotes 蓝牙驱动相关代码_蓝牙驱动代码-CSDN博客 linux蓝牙驱动代码阅读笔记_bt-sco.c-CSDN博客 Linux内核的蓝牙子系统架构-CSDN博客 …

22. 仿LISP运算

题目描述 LISP语言唯一的语法就是括号要配对 形如(OP P1 P2 ...),括号内元素由单个空格分割。其中第一个元素OP为操作符,后续元素均为其参数,参数个数取决于操作符类型。注意:参数P1,P2也有可能是另外一个嵌套的(OP P1 P2...),当前…

Axure10

如果还是不行就将字体图标安装在控制面板–字体下 打开原型了之后,icon没有 一定要将字体库放到–》控制面板\外观和个性化\字体 里面

王佩丰24节Excel学习笔记——第十九讲:Indirect函数

【以 Excel2010 系列学习,用 Office LTSC 专业增强版 2021 实践】 【本章技巧】 如果indirect引用出错,首先检查一下引用位置的双引号有没有出错,再检查引用值的位置是否出错,如果是双引号出错,可以使用英文状态下输入…

基于 Ragflow 搭建知识库-初步实践

基于 Ragflow 搭建知识库-初步实践 一、简介 Ragflow 是一个强大的工具,可用于构建知识库,实现高效的知识检索和查询功能。本文介绍如何利用 Ragflow 搭建知识库,包括环境准备、安装步骤、配置过程以及基本使用方法。 二、环境准备 硬件要…

Structured-Streaming初识

一、概览 Structured Streaming是一个基于SparkSQL引擎构建的可扩展且容错的流处理引擎。可以像在静态数据上表达批量计算一样表达流计算。SparkSQL引擎将负责以增量方式连续运行它,并在流数据继续到达时更新最终结果。可以使用Scala、Java、Python或R中的Dataset/…

Gradio全解系列——Additional Features:附加功能(上)

Gradio全解系列——Additional Features:附加功能(上) 前言本篇摘要10. Additional Features:附加功能10.1 队列10.1.1 使用方法10.1.2 配置队列 10.2 流输入输出10.2.1 流输出1. 生成器yield2. 流媒体 10.2.2 流输入1. 流事件2. …

TestMAX/DFT Compiler:时序单元的类型、连接顺序和后DFT优化

相关阅读 TestMAX/DFT Compilerhttps://blog.csdn.net/weixin_45791458/category_12865937.html?spm1001.2014.3001.5482 时序单元的状态 未映射的时序单元(Unmapped Sequential Cell) 在Design Compiler读取了一个RTL设计后,Design Compiler内置的HDL Compiler工…

Cocos Creator 3.8.5 正式发布,更小更快更多平台!

在 Cocos Creator 3.8.5 版本中,我们做了新一轮的优化。 在加载速度、代码裁剪、平台增强等多方面做了优化,提升了开发者体验和游戏性能。 希望能够助 Cocos 开发者们的产品更上一层楼。 一、加载速度优化 1、WASM 模块延迟加载 在早期版本中&#xff0c…