HTML 5 离线数据库(indexedDB 和 WebSql)的非常简单的示例






4.80/5 (20投票s)
本文介绍了在处理 HTML 5 离线应用程序时用于在数据库(indexedDB 和 WebSql)中创建、编辑、修改或删除表数据的浏览器数据库的基本知识。
引言
此应用程序仅供参考,而非教学。我在这篇文章中与我一样的初学者分享了我代码的一小部分。我将很高兴收到您的建议或任何评论。
本文试图解释浏览器数据库的基本知识,这在处理 HTML 5 离线应用程序时非常有用。开发者如何开发一个能够与浏览器本地数据库交互、插入新记录、修改或编辑表中现有记录、获取表中的所有记录或特定记录以及删除表中记录的 Web 应用程序。
背景
为了使我们的 Web 应用程序能够离线工作,我们需要两样东西:
CACHE.APPCACHE
:将所有必需的文件(HTML 页面、JavaScript 文件、图像等)获取到本地浏览器DATABASE
:用于在本地存储用户工作数据的数据库
CACHE.APPCACHE
第一点可以使用 HTML 5 的一个新功能 `cache.appcache` 文件来实现。您可以轻松找到关于 `cache.appcache` 文件的有用教程,并且使用此文件实现缓存非常容易。对于我们的项目,我们不会编写一个硬编码的文件,在这个项目中,我们将实现一个将作为此文件服务器的 **Action Result**。
数据库
现在这是本文最重要的部分。任何应用程序都需要数据库来存储信息/记录,就像服务器端的 SQL Server 一样。由于我们正在实现一个离线应用程序,我们需要一个数据库来存储信息/记录。对于离线应用程序,不同的浏览器支持两种类型的数据库。
WebSql
适用于 Safari 类浏览器IndexedDB
适用于 Mozilla、Chrome、Internet Explorer 类浏览器。
WebSql
:这是一个基于查询的数据库,类似于 SQL Server。您需要像在 SQL Server 中一样编写查询来插入
、更新
和删除
记录。此数据库用于 Safari 浏览器。
IndexedDB
:这个数据库基于对象,我们不需要为它编写查询。它只是用于添加
、更新
和删除
对象。对于这个数据库,我们将使用 Aaron Powell 提供的一个 `db.js` 包装文件。我们将此数据库用于 Safari 浏览器以外的所有浏览器。
Using the Code
缓存清单 Action 的实现
// Cache Action
public ActionResult Manifest()
{
var manifest = "CACHE MANIFEST" + Environment.NewLine +
"# App Version: " + System.IO.File.GetLastWriteTime
(Server.MapPath("~/Views/Home/Index.cshtml")) + Environment.NewLine +
"# Server Assembly Version: " + this.GetType().Assembly.GetName().Version +
Environment.NewLine +
"NETWORK:" + Environment.NewLine +
"*" + Environment.NewLine +
"CACHE:" + Environment.NewLine +
Url.Action("Index", "Home") + Environment.NewLine +
Url.Content("~/Content/site.css") + Environment.NewLine +
Url.Content("~/Content/bootstrap.min.css") + Environment.NewLine +
Url.Content("~/scripts/jquery-1.7.1.js") + Environment.NewLine +
Url.Content("~/scripts/bootstrap.min.js") + Environment.NewLine +
Url.Content("~/scripts/bootbox.min.js") + Environment.NewLine +
Url.Content("~/scripts/db.js") + Environment.NewLine +
Url.Content("~/scripts/Config.js") + Environment.NewLine +
Url.Content("~/scripts/DbManager.js") + Environment.NewLine +
Url.Content("~/scripts/index.js") + Environment.NewLine +
Url.Content("~/scripts/jquery.blockUI.js") + Environment.NewLine +
Url.Content("~/scripts/cache.js") + Environment.NewLine;
return Content(manifest, "text/cache-manifest");
}
这个 `Action` 结果包含三行主要代码。
这行代码设置了 `cache.appcache` 文件的版本。每当您更改主视图中的任何内容时,这将强制浏览器从服务器获取新文件。
"# App Version: " + System.IO.File.GetLastWriteTime
(Server.MapPath("~/Views/Home/Index.cshtml")) + Environment.NewLine +
要添加新文件,可以使用这行代码添加文件:
Url.Content("~/Content/site.css") + Environment.NewLine +
此 Action 的返回类型设置为“text/cache-manifest
”类型。
return Content(manifest, "text/cache-manifest");
现在,要将此清单添加到您的布局或页面,只需将此行添加到您的页面 `html` 标记中。
html manifest="@Url.Action("Manifest", "Home")"
好了,缓存清单代码就完成了。
数据库的实现
现在我们将有两个代码块部分,一个用于 `websql`,另一个用于 `indexedDb`。首先,我们需要识别它是否是 Safari 浏览器。如果是 Safari 浏览器,我们将使用 `websql`,否则使用 `indexedDB`。
if (navigator.userAgent.indexOf("Safari") >= 0
&& navigator.userAgent.indexOf("Chrome") < 0) {
//SAFARI BROWSER SO WEBSQL IMPLEMENTATION HERE
}else{
//OTHER BROWSERS SO INDEXEDDB IMPLEMENTATION HERE
}
现在,我们需要初始化我们的数据库。
if (navigator.userAgent.indexOf("Safari") >= 0
&& navigator.userAgent.indexOf("Chrome") < 0) {
var DataBaseManager = {
Offlinedb: openDatabase("OfflineDB", '1', 'my first database',
2 * 1024 * 1024)//this accept four parameters 1. database name,
//2. version, 3. Comments, 4.initial Size
}
}else{
//For indexedDB the db.js file automatically initialize the database.
//So we just need to provide the schema and database name during our database operations.
}
现在,在继续之前,我们首先将为 `indexedDB` 声明一个全局 schema 对象,其中包含一个 `UserData` 表,`UserID` 设置为 `true`(自动递增)。
var OfflineConfiguration = {
Db_VERSION: 1,
DB_NAME: "OfflineDB",
SCHEMA: {
UserData: { key: { keyPath: 'UserID', autoIncrement: true } }
}
};
现在我们有了一个用于存储应用程序数据库的数据服务器,我们需要定义数据库的 schema。对于 `WebSql`,我们将使用查询来定义表结构,对于 `IndexedDb`,我们将使用对象来定义 schema。我们的应用程序使用单个表,即 `UserData`,而 `UserID` 是一个自动递增的标识列。
if (navigator.userAgent.indexOf("Safari") >= 0
&& navigator.userAgent.indexOf("Chrome") < 0) {
var DataBaseManager = {
Offlinedb: openDatabase("OfflineDB", '1', 'my first database', 2 * 1024 * 1024),
initializeDataBase: function () {
var self = this;
self.Offlinedb.transaction(function (tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS UserData
(UserID INTEGER PRIMARY KEY AUTOINCREMENT, Name, Email, Technology)');
});
},
}
}else{
var DataBaseManager = {
//For indexedDB we will not have any initialize function
//as we already define the schema for this globally.
}
}
数据操作
现在,我们有了表,就可以进行数据操作了:`ADD`(添加)、`GET`(获取)、`UPDATE`(更新)和 `DELETE`(删除)。
1. 添加用户
if (navigator.userAgent.indexOf("Safari") >= 0
&& navigator.userAgent.indexOf("Chrome") < 0) {
var DataBaseManager = {
Offlinedb: openDatabase("OfflineDB", '1', 'my first database', 2 * 1024 * 1024),
initializeDataBase: function () {
var self = this;
self.Offlinedb.transaction(function (tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS UserData
(UserID INTEGER PRIMARY KEY AUTOINCREMENT, Name, Email, Technology)');
});
},
AddnewUser: function (data, callback) {//data: contains the object of user ,
// callback: is a function will execute after the addition
this.initializeDataBase();
var self = this;
self.Offlinedb.transaction(function (tx) {
var query = "insert into UserData(Name,Email,Technology) values(?,?,?)";
tx.executeSql(query, [data.Name, data.Email, data.Technology],
function (tx, results) {
if (callback) callback("User Saved");
});
});
}
}
}else{
var DataBaseManager = {
//For indexedDB we will not have any initialize function as we already define
//the schema for this globally.
AddnewUser: function (data, callback) {//data: contains the object of user ,
// callback: is a function will execute after the addition
db.open({
server: OfflineConfiguration.DB_NAME,//database name defined globally
version: OfflineConfiguration.Db_VERSION,//version defined globally
schema: OfflineConfiguration.SCHEMA//schema defined globally
}).done(function (s) {
self.Server = s;
self.Server.UserData.add(data).done(function (results) {
if (callback) callback("Data added into UserData");
});
});
},
}
}
2. 获取用户
if (navigator.userAgent.indexOf("Safari") >=0
&& navigator.userAgent.indexOf("Chrome") < 0) {
var DataBaseManager = {
.....
GetSingleUser: function (data, callback) {//data: contains the UserID ,
// callback: is a function will execute after the selection
try {
var self = this;
this.initializeDataBase();
var query1 = "SELECT * from UserData where UserID=" + data;
self.Offlinedb.transaction(function (tx) {
tx.executeSql(query1, [], function (tx, results) {
if (results.rows.length > 0) {
var v = results.rows.item(0);
if (callback) callback(results.rows.item(0));
} else {
if (callback) callback("Not Found");
}
});
});
}
catch (e) {
console.log(" error occurred in selecting data");
}
},
....
}
}else{
var DataBaseManager = {
....
GetSingleUser: function (data, callback) {//data: contains the UserID ,
//callback: is a function will execute after the selection
db.open({
server: OfflineConfiguration.DB_NAME,
version: OfflineConfiguration.Db_VERSION,
schema: OfflineConfiguration.SCHEMA
}).done(function (s) {
self.Server = s
self.Server.UserData
.query()
.all()
.filter(function (result) {
return result.UserID === parseInt(data);
})
.execute()
.done(function (finalResult) {
if (callback) callback(finalResult);
});
});
},
....
}
}
3. 更新用户
if (navigator.userAgent.indexOf("Safari") >=0
&& navigator.userAgent.indexOf("Chrome") < 0) {
var DataBaseManager = {
.....
UpdateUser: function (data, callback) {//data: contains the object of user ,
// callback: is a function will execute after the updation
try {
this.initializeDataBase();
var self = this;
var query1 = "update UserData set Name=?,Email=?,Technology=? where UserID=?";
self.Offlinedb.transaction(function (tx) {
tx.executeSql(query1, [data.Name, data.Email,
data.Technology, parseInt(data.UserID)], function (tx, results) {
if (callback) callback("Response updated");
});
});
}
catch (e) {
console.log(" error occurred in selecting data");
}
},
....
}
}else{
var DataBaseManager = {
....
UpdateUser: function (data, callback) {//data: contains the object of user ,
// callback: is a function will execute after the updation
db.open({
server: OfflineConfiguration.DB_NAME,
version: OfflineConfiguration.Db_VERSION,
schema: OfflineConfiguration.SCHEMA
}).done(function (s) {
self.Server = s
self.Server.UserData.update(data).done(function (item) {
if (callback) callback("response updated to database");
});
});
},
....
}
}
4. 删除用户
if (navigator.userAgent.indexOf("Safari") >=0
&& navigator.userAgent.indexOf("Chrome") < 0) {
var DataBaseManager = {
.....
DeleteUser: function (data, callback) {//data: contains the UserID of user ,
// callback: is a function will execute after the deletion
try {
this.initializeDataBase();
var self = this;
self.Offlinedb.transaction(function (tx) {
tx.executeSql("Delete from UserData where UserID=?",
[data], function (tx, results) {
if (callback) callback("Data deleted");
});
});
}
catch (e) {
}
}
....
}
}else{
var DataBaseManager = {
....
DeleteUser: function (data, callback) {//data: contains the UserID of user ,
// callback: is a function will execute after the deletion
var self = this;
db.open({
server: OfflineConfiguration.DB_NAME,
version: OfflineConfiguration.Db_VERSION,
schema: OfflineConfiguration.SCHEMA
}).done(function (s) {
self.Server = s
self.Server.UserData.remove(data).done(function (a) {
if (callback) callback("Data deleted");
});
});
}
....
}
}
好了!我们完成了四种数据操作。
这些操作的用途
您可以参考 `index.js` 文件,其中我实现了这些操作的用法。
1. 添加新用户操作的用法
var data = '{"Name":"Vinu","Email":"itvinay12@gmail.com",
"Technology":".NET"}';//user object
data = JSON.parse(data);
DataBaseManager.AddnewUser(data, GetAllUser);// GetAllUser is a
//function defined in index.js you can refer it.
2. 获取用户操作的用法
DataBaseManager.GetSingleUser(1, anycallbackfunction);// Get the details of user with id 1.
3. 更新用户操作的用法
var data = '{"UserID":1,"Name":"Vinu",
"Email":"itvinay12@gmail.com","Technology":".NET"}';//user object with UserID
data = JSON.parse(data);
DataBaseManager.UpdateUser(data, GetAllUser);// GetAllUser is a
//function defined in index.js you can refer it.
4. 删除用户操作的用法
DataBaseManager.DeleteUser(1,GetAllUser);// delete the details of user with id 1.
关注点
我只想建议一点:在开始这类应用程序之前,请选择最好的 JavaScript 框架,并阅读有关浏览器兼容性的信息。
历史
- 2014年9月18日:首次发布