使用 HTML5 WebDatabases 的简单待办事项列表

简介

网络数据库是 HTML5 中的新增功能。Web 数据库托管在用户的浏览器中,并持久保留。通过让开发者能够创建具有丰富查询功能的应用,我们可以想象将涌现出能够在线和离线工作的新型 Web 应用。

本文中的示例代码演示了如何创建一个非常简单的待办事项列表管理器。这是对 HTML5 中部分功能的详细介绍

前提条件

此示例使用命名空间来封装数据库逻辑。

var html5rocks = {};
html5rocks.webdb = {};

异步和事务

在大多数情况下,如果您使用 Web 数据库支持,都将使用异步 API。异步 API 是一个非阻塞系统,因此不会通过返回值获取数据,而是获取传递给定义的回调函数的数据。

通过 HTML 支持网络数据库是一项事务性功能。在事务之外无法执行 SQL 语句。事务有两种类型:读/写事务 (transaction()) 和只读事务 (readTransaction())。请注意,读/写会锁定整个数据库。

第 1 步:打开数据库

数据库必须先打开,然后才能访问。
您需要定义数据库的名称、版本、说明和大小。

html5rocks.webdb.db = null;

html5rocks.webdb.open = function() {
var dbSize = 5 * 1024 * 1024; // 5MB
html5rocks.webdb.db = openDatabase("Todo", "1", "Todo manager", dbSize);
}

html5rocks.webdb.onError = function(tx, e) {
alert("There has been an error: " + e.message);
}

html5rocks.webdb.onSuccess = function(tx, r) {
// re-render the data.
// loadTodoItems is defined in Step 4a
html5rocks.webdb.getAllTodoItems(loadTodoItems);
}

第 2 步:创建表

您只能通过在事务内执行 CREATE TABLE SQL 状态器来创建表。

我们定义了一个在正文 onload 事件中创建表的函数。如果该表尚不存在,系统会创建一个。

该表称为待办事项,有 3 列。

  • ID - 递增的顺序 ID 列
  • 待办事项 - 作为清单项正文的文本列
  • added_on - 创建待办事项的时间
html5rocks.webdb.createTable = function() {
var db = html5rocks.webdb.db;
db.transaction(function(tx) {
tx.executeSql("CREATE TABLE IF NOT EXISTS " +
                "todo(ID INTEGER PRIMARY KEY ASC, todo TEXT, added_on DATETIME)", []);
});
}

第 3 步:将数据添加到表中

我们要构建的是待办事项列表管理器,因此能够向数据库中添加待办事项非常重要。

系统会创建一个事务,并在事务内执行对待办事项表的插入操作。

executeSql 需要几个参数、要执行的 SQL 以及用于绑定查询的参数值。

html5rocks.webdb.addTodo = function(todoText) {
var db = html5rocks.webdb.db;
db.transaction(function(tx){
var addedOn = new Date();
tx.executeSql("INSERT INTO todo(todo, added_on) VALUES (?,?)",
    [todoText, addedOn],
    html5rocks.webdb.onSuccess,
    html5rocks.webdb.onError);
});
}

第 4 步:从表格中选择数据

既然数据在数据库中,您接下来就需要用一个函数来取回数据。在 Chrome 中,网络数据库使用标准的 SQLite SELECT 查询。

html5rocks.webdb.getAllTodoItems = function(renderFunc) {
var db = html5rocks.webdb.db;
db.transaction(function(tx) {
tx.executeSql("SELECT * FROM todo", [], renderFunc,
    html5rocks.webdb.onError);
});
}

请注意,此示例中使用的所有这些命令都是异步的,因此数据不会从事务或 executeSql 调用中返回。结果会传递到成功回调。

第 4a 步:呈现表中的数据

从表中提取数据后,将调用 loadTodoItems 方法。

onSuccess 回调需要两个参数。第一个是查询的事务,第二个是结果集。迭代数据非常简单:

function loadTodoItems(tx, rs) {
var rowOutput = "";
var todoItems = document.getElementById("todoItems");
for (var i=0; i < rs.rows.length; i++) {
rowOutput += renderTodo(rs.rows.item(i));
}

todoItems.innerHTML = rowOutput;
}
function renderTodo(row) {
return "<li>" + row.todo + 
        " [<a href='javascript:void(0);' onclick=\'html5rocks.webdb.deleteTodo(" + 
        row.ID +");\'>Delete</a>]</li>";
}

此方法调用的效果是,待办事项列表会被渲染到一个名为“todoItems”的 DOM 元素。

第 5 步:从表中删除数据

html5rocks.webdb.deleteTodo = function(id) {
var db = html5rocks.webdb.db;
db.transaction(function(tx){
tx.executeSql("DELETE FROM todo WHERE ID=?", [id],
    html5rocks.webdb.onSuccess,
    html5rocks.webdb.onError);
});
}

第 6 步:全部连接

页面加载时,打开数据库并创建表(如果需要),然后呈现数据库中可能已存在的任何待办事项。

....
function init() {
html5rocks.webdb.open();
html5rocks.webdb.createTable();
html5rocks.webdb.getAllTodoItems(loadTodoItems);
}
</script>

<body onload="init();">

这需要用到可将数据取出 DOM 的函数,即 html5rocks.webdb.addTodo 方法

function addTodo() {
var todo = document.getElementById("todo");
html5rocks.webdb.addTodo(todo.value);
todo.value = "";
}