IndexedDB技术简介(三)

本文摘自 勾三股四 更早时期的 不老歌 博客。


今天做一个IndexedDB(以下简称IDB)的demo,运行环境是Firefox 10。

DEMO演示链接 (firefox 10+ only)

我们做一个阅读列表的页面,可以让用户把任意网址存入这个阅读列表中,并为每一个网址起一个名字,也可以随时删除,且列表可以按网址自动去重。

正如上一篇文章介绍的步骤,我们先初始化数据库,然后建表,然后把添加/删除/读取网址的事件和数据库操作绑定在一起。

首先是html代码:

<body onload="<strong>init()</strong>">
    _button onclick="<strong>clickAddBtn()</strong>">Add_/button>
    _ul <strong>id="list"</strong>>_/ul>
</body>

为了演示方便,我们引入jQuery作界面处理,再声明一个全局变量db,作为数据库连接的句柄;再声明一个全局变量list,作为网页中列表元素的jQuery句柄。

var db;
var list = $('#list');

然后定义数据库初始化的行数init

function init() {
    var req = window.<strong>mozIndexedDB</strong>.open('readinglist', '1.0');
    req.onsuccess = function (e) {
        <strong>db = this.result;</strong>
        // TODO: 连接成功后展示列表
    };
    req.onupgradeneeded = function (e) {
        <strong>db = this.result;</strong>
        // TODO: 版本不同时创建一个新的object store
    };
}

这段代码的作用是初始化数据库(readinglist)连接,并在第一次连接数据库时创建表(links)。我们把展示列表的函数定义为showList(),把创建表的代码也补充完整,即:

function init() {
    var req = window.mozIndexedDB.open('readinglist', '1.0');
    req.onsuccess = function (e) {
        db = this.result;
        <strong>showList();</strong>
    };
    req.onupgradeneeded = function (e) {
        db = this.result;
        <strong>db.createObjectStore('links', {keyPath: 'url'});</strong>
    };
}

然后我们定义添加/删除/展示链接的函数:add(title, url)/remove(url)/showList()

function add(<strong>title, url</strong>) {
    var <strong>link</strong> = {
        title: title,
        url: url
    }; // 创建要存储的对象
    var transaction = db.transaction('links', IDBTransaction.READ_WRITE);
    var store = transaction.objectStore('links');
    <strong>var req = store.put(link);</strong> // put的作用是key存在时做更新处理,不存在是做添加处理
    <strong>req.onsuccess = showList;</strong> // 添加成功后重新展示列表
}

function remove(<strong>url</strong>) {
    var transaction = db.transaction('links', IDBTransaction.READ_WRITE);
    var store = transaction.objectStore('links');
    <strong>var req = store.delete(url);</strong> // 删除此链接
    <strong>req.onsuccess = showList;</strong> // 删除成功后重新展示列表
}

function showList() {
    // TODO: clear element: #list

    var transaction = db.transaction('links');
    var store = transaction.objectStore('links');
    <strong>var range = IDBKeyRange.lowerBound(0);</strong> // 创建关键字范围描述
    <strong>var req = store.openCursor(range);</strong> // 创建在上述范围内遍历的游标
    req.onsuccess = function (e) {
        var result = this.result;
        if (result) {
            var link = result.value;
            // TODO: append this link to element: #list
            <strong>result.continue();</strong>
        }
    };
}

注意这里的IDBKeyRangestore.openCursor是用来遍历列表的,前者确定遍历的范围,后者根据前者的范围逐条触发onsuccess事件,这里定义的遍历范围是大于0,即所有非空的url,其实所有js类型的值都是可以在一起比大小的,如果想测试比较任意两个key的大小,可以运行函数window.mozIndexedDB.cmp(any first, any second)

最后,我们把最后两个TODO的部分补充完整,再把界面上的事件绑定好。编码工作就完成了。

function showList() {
    <strong>list.empty();</strong>

    var transaction = db.transaction('links');
    var store = transaction.objectStore('links');
    var range = IDBKeyRange.lowerBound(0); // 创建关键字范围描述
    var req = store.openCursor(range); // 创建在上述范围内遍历的游标
    req.onsuccess = function (e) {
        var result = this.result;
        if (result) {
            var link = result.value;
            <strong>appendLink(link);</strong>
            result.continue();
        }
    };
}

function appendLink(link) {
    var url = link.url;
    var title = link.title;
    var li = $('_li>_a href="#" target="_blank">_/a> _button>X_/button>_/li>');
    li.find('a').attr('title', title).attr('href', url).text(title);
    li.find('button').click(function (e) {
        <strong>remove(link.url);</strong>
    });
    list.append(li);
}

function clickAddBtn(e) {
    var title = prompt('please input the title') || '[No title]';
    var url = prompt('please input the url', 'http://');
    if (title && url) {
        <strong>add(title, url);</strong>
    }
}

DEMO演示链接 (firefox 10+ only)

下一篇讨论webkit下使用IDB的注意事项,并提供兼容问题的解决办法。

(未完待续)