JavaScript 离线运用与客户端存储——“数据存储”的注重要点

Cookie

限定

由于浏览器存在种种限定,最好将悉数cookie长度限定在4095B之内。

构成

cookie由浏览器保留的以下几块信息构成:

  • 称号: cookie的称号必需是经由URL编码后的字符串。 虽然它是不辨别大小写的, 然则现实运用时提议把它看成辨别大小写来运用。

  • 值: cookie中字符串值, 也必需是经由URI编码的字符串。

  • 域: 示意cookie关于哪一个域有用。

  • 途径: cookie是针对域中的哪一个目次见效。

  • 失效时刻: 示意cookie失效时刻的时刻戳, 它是GMT花样的日期。 将该事宜设置小于当前时, 就相当于删除了cookie。

  • 平安标识: 指定该标识后, 只需运用SSL要求衔接的时刻cookie才会发送到服务器。 secure标识是cookie中唯一一个非键值对的部份, 它只包含一个secure单词。

运用分号加空格离开各个信息构成:

HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie: CookieName=CookieValue; expires=Mon, 22-Jan-07 07:10:24 GMT; domain=.wrox.com
Other-header: other-header-value

或运用平安标志:

HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie: CookieName=CookieValue; expires=Mon, 22-Jan-07 07:10:24 GMT; domain=.wrox.com; path=/; secure //在这里!
Other-header: other-header-value

JavaScript中的Cookie

在JavaScript中能够经由过程

document.cookie能够读取当前域名下的cookie, 是用分号离隔的键值对构成的字符串。 相似于name = aa;
age = 15;

注重一切的键值对称号和值都是经由encodeURIComponent() 编码的, 运用时要举行解码。

当给document.cookie赋值时, 不会直接掩盖现有的cookie, 而是会追加一个新的cookie。 比方:

document.cookie = "a=1"; //实行后会看到新增了一个cookie。

如:

document.cookie = encodeURIComponent("name") + "=" + encodeURIComponent("Oliver");
console.log(document.cookie); //name=Oliver;

假如给cookie赋值则会增添一个cookie:

document.cookie = encodeURIComponent("name") + "=" + encodeURIComponent("Oliver");
document.cookie = encodeURIComponent("age") + "=" + encodeURIComponent("18");
console.log(document.cookie); //name=Oliver; age=18

以下函数是经常使用的cookie读写删除要领:

var CookieUtil = {
    //依据key读取cookie
    get: function(name) {
        //注重对键编码
        var cookieName = encodeURIComponent(name) + "=",
            cookieStart = document.cookie.indexOf(cookieName),
            cookieValue = null,
            cookieEnd;
        //找到cookie键   
        if (cookieStart > -1) {
            //键背面第一个分号位置
            cookieEnd = document.cookie.indexOf(";", cookieStart);
            if (cookieEnd == -1) {
                cookieEnd = document.cookie.length;
            }
            //cookie值解码
            cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd));
        }
        return cookieValue;
    },
    //设置cookie
    set: function(name, value, expires, path, domain, secure) {
        var cookieText = encodeURIComponent(name) + "=" + encodeURIComponent(value);
        //失效时刻,GMT时刻花样
        if (expires             instanceof Date) {
            cookieText += "; expires=" + expires.toGMTString();
        }
        if (path) {
            cookieText += "; path=" + path;
        }
        if (domain) {
            cookieText += "; domain=" + domain;
        }
        if (secure) {
            cookieText += "; secure";
        }
        document.cookie = cookieText;
    },
    //删除cookie,坚持雷同的键、域、途径、平安选项,然后设置失效时刻即可
    unset: function(name, path, domain, secure) {
        this.set(name, "", new Date(0), path, domain, secure);
    }
};

能够像下面如许运用上述要领:

设置cookie:

CookieUtil.set("name","Oliver");
CookieUtil.set("age","18");
console.log(document.cookie); //name=Oliver; age=18 

读取cookie的值:

console.log(CookieUtil.get("name")); //Oliver

删除cookie:

CookieUtil.unset("name"); //
console.log(document.cookie); //age=18 

设置cookie途径、域等:

CookieUtil.set("name","Oliver","/","localhost",null,false);

不然运用下面的代码竖立和删除cookie:

//新cookie
document.cookie = encodeURIComponent("name") + "=" + encodeURIComponent("Oliver");
//删除上面竖立的cookie
document.cookie = encodeURIComponent("name") + "=" + encodeURIComponent("Oliver") + "; expires=" + new Date(0);

举例

css:

<style type="text/css">
*{
    margin: 0;
    padding: 0;
}
div#message {
    border: 1px solid #ccc;
    min-height: 3em;
    background-color: #33CCFF;
    margin: 0;
}
p#content{
    color:white;
    font-size: 2em;
    margin:0.3em;
    font-family: monospace;
    display: inline-block;
    float: left;
    /*border: 1px solid gray;*/
}
a#notShow {
    width: 2em;
    display: block;
    height: 1em;
    float: right;
    /*border: 1px solid gray;*/
}
</style>

DOM:

<div id="message">
    <p id="content">welcome to my site!</p>
    <a href="" id="notShow">封闭</a>
</div>

js:

<script type="text/javascript">
//CookieUtil函数
var CookieUtil = {...}
//猎取元素
var messageDiv = document.getElementById("message");
var notShowBtn = document.getElementById("notShow");
//点击封闭按钮新建cookie并封闭banner
notShowBtn.onclick = function () {
    event.preventDefault();
    CookieUtil.set("hideMessage", "hide");
    messageDiv.style.display = "none";
};
//搜检cookie当存在则封闭banner
window.onload = function () {
    if (CookieUtil.get("hideMessage")) {
        messageDiv.style.display = "none";
    }
};
</script>

子Cookie

由于浏览器cookie数目是有限定的,为了削减cookie数目能够运用子cookie的体式格局。在一个cookie值中运用相似查询字符串的花样能够存储多组键值对,如许就没必要每一个键值对都占用一个cookie了。子cookie值举例:

name=name1=value1&name2=value2

猎取一切子cookie

猎取一切子cookie并将它放在一个对象中返回,对象的属性名为子cookie称号,对象的属性值为子cookie的值。

getAll: function(name) {
        var cookieName = encodeURIComponent(name) + "=",
            cookieStart = document.cookie.indexOf(cookieName),
            cookieValue = null,
            cookieEnd,
            subCookies,
            i,
            parts,
            result = {};
        if (cookieStart > -1) {
            cookieEnd = document.cookie.indexOf(";", cookieStart)
            if (cookieEnd == -1) {
                cookieEnd = document.cookie.length;
            }
            //掏出cookie字符串值
            cookieValue = document.cookie.substring(cookieStart + cookieName.length, cookieEnd);
            if (cookieValue.length > 0) {
                //用&将cookie值分开成数组
                subCookies = cookieValue.split("&");
                for (i = 0, len = subCookies.length; i < len; i++) {
                    //等号分开出键值对
                    parts = subCookies[i].split("=");
                    //将解码后的兼职对离别作为属性称号和属性值赋给对象
                    result[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]);
                }
                return result;
            }
        }
        return null;
    }

猎取单个子cookie

get()猎取单个子cookie。

get: function(name, subName) {
        //猎取一切子cookie
        var subCookies = this.getAll(name);
        if (subCookies) {
            //从属性中猎取单个子cookie
            return subCookies[subName];
        } else {
            return null;
        }
    }

设置悉数cookie

setAll设置悉数cookie

setAll: function(name, subcookies, expires, path, domain, secure) {
        var cookieText = encodeURIComponent(name) + "=",
            subcookieParts = new Array(),
            subName;
        //遍历子cookie对象的属性
        for (subName in subcookies) {
            //要先检测属性名
            if (subName.length > 0 && subcookies.hasOwnProperty(subName)) {
                //属性名和属性值编码后=衔接为字符串,并放到数组中
                subcookieParts.push(encodeURIComponent(subName) + "=" + encodeURIComponent(subcookies[subName]));
            }
        }
        if (subcookieParts.length > 0) {
            //用&衔接子cookie串
            cookieText += subcookieParts.join("&");
            if (expires instanceof Date) {
                cookieText += "; expires=" + expires.toGMTString();
            }
            if (path) {
                cookieText += "; path=" + path;
            }
            if (domain) {
                cookieText += "; domain=" + domain;
            }
            if (secure) {
                cookieText += "; secure";
            }
        } else {
            cookieText += "; expires=" + (new Date(0)).toGMTString();
        }
        //设置悉数cookie
        document.cookie = cookieText;
    }

设置单个子cookie

set设置单个子cookie

set: function(name, subName, value, expires, path, domain, secure) {
        //猎取当前cookie对象
        var subcookies = this.getAll(name) || {};
        //单个cookie对应的属性替代
        subcookies[subName] = value;
        //从新设置cookie
        this.setAll(name, subcookies, expires, path, domain, secure);
    }

删除cookie

删除悉数cookie, 将失效时刻设置为逾期日期即可。

unsetAll: function(name, path, domain, secure) {
        this.setAll(name, null, new Date(0), path, domain, secure);
    }

删除单个子cookie

删除单个子cookie,须要先猎取一切子cookie对象,然后删除子cookie对应的属性,末了再将子cookie对象从新设置归去。

unset: function(name, subName, path, domain, secure) {
        //猎取当前cookie对象
        var subcookies = this.getAll(name);
        if (subcookies) {
            //删除子cookie对应的属性
            delete subcookies[subName];
            //从新设置cookie
            this.setAll(name, subcookies, null, path, domain, secure);
        }
    }

以下函数是经常使用的子cookie读写删除要领:

var SubCookieUtil = {
    getAll: function(name) {
        var cookieName = encodeURIComponent(name) + "=",
            cookieStart = document.cookie.indexOf(cookieName),
            cookieValue = null,
            cookieEnd,
            subCookies,
            i,
            parts,
            result = {};
        if (cookieStart > -1) {
            cookieEnd = document.cookie.indexOf(";", cookieStart)
            if (cookieEnd == -1) {
                cookieEnd = document.cookie.length;
            }
            //掏出cookie字符串值
            cookieValue = document.cookie.substring(cookieStart + cookieName.length, cookieEnd);
            if (cookieValue.length > 0) {
                //用&将cookie值分开成数组
                subCookies = cookieValue.split("&");
                for (i = 0, len = subCookies.length; i < len; i++) {
                    //等号分开出键值对
                    parts = subCookies[i].split("=");
                    //将解码后的兼职对离别作为属性称号和属性值赋给对象
                    result[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]);
                }
                return result;
            }
        }
        return null;
    },
    get: function(name, subName) {
        //猎取一切子cookie
        var subCookies = this.getAll(name);
        if (subCookies) {
            //从属性中猎取单个子cookie
            return subCookies[subName];
        } else {
            return null;
        }
    },
    setAll: function(name, subcookies, expires, path, domain, secure) {
        var cookieText = encodeURIComponent(name) + "=",
            subcookieParts = new Array(),
            subName;
        //遍历子cookie对象的属性
        for (subName in subcookies) {
            //要先检测属性名
            if (subName.length > 0 && subcookies.hasOwnProperty(subName)) {
                //属性名和属性值编码后=衔接为字符串,并放到数组中
                subcookieParts.push(encodeURIComponent(subName) + "=" + encodeURIComponent(subcookies[subName]));
            }
        }
        if (subcookieParts.length > 0) {
            //用&衔接子cookie串
            cookieText += subcookieParts.join("&");
            if (expires instanceof Date) {
                cookieText += "; expires=" + expires.toGMTString();
            }
            if (path) {
                cookieText += "; path=" + path;
            }
            if (domain) {
                cookieText += "; domain=" + domain;
            }
            if (secure) {
                cookieText += "; secure";
            }
        } else {
            cookieText += "; expires=" + (new Date(0)).toGMTString();
        }
        //设置悉数cookie
        document.cookie = cookieText;
    },
    set: function(name, subName, value, expires, path, domain, secure) {
        //猎取当前cookie对象
        var subcookies = this.getAll(name) || {};
        //单个cookie对应的属性替代
        subcookies[subName] = value;
        //从新设置cookie
        this.setAll(name, subcookies, expires, path, domain, secure);
    },
    unsetAll: function(name, path, domain, secure) {
        this.setAll(name, null, new Date(0), path, domain, secure);
    },
    unset: function(name, subName, path, domain, secure) {
        //猎取当前cookie对象
        var subcookies = this.getAll(name);
        if (subcookies) {
            //删除子cookie对应的属性
            delete subcookies[subName];
            //从新设置cookie
            this.setAll(name, subcookies, null, path, domain, secure);
        }
    }
};

举例:

猎取cookie:

//若cookie为document.cookie=data=name=Oliver&book=jsbook;
document.cookie = "data" + "=" + "name" + "=" + "Oliver" + "&" + "book" + "=" + "jsbook";
//取得悉数子cookie
var data = SubCookieUtil.getAll("data");
console.log(data.name); //Oliver
console.log(data.book); //jsbook
//猎取单个子cookie
data = SubCookieUtil.get("data", "name");
console.log(data); //Oliver
console.log(document.cookie); //data=name=Oliver&book=jsbook

设置cookie:

//若cookie为document.cookie=data=name=Oliver&book=jsbook;
document.cookie = "data" + "=" + "name" + "=" + "Oliver" + "&" + "book" + "=" + "jsbook";
//设置两个cookie
SubCookieUtil.set("data", "name", "Nicholas");
SubCookieUtil.set("data", "book", "HTMLreference")
console.log(document.cookie); //data=name=Nicholas&book=HTMLreference
//设置悉数子cookie
SubCookieUtil.setAll("data", { name: "Troy", book: "JSON"});
console.log(document.cookie); //data=name=Troy&book=JSON
//修正部份子cookie
SubCookieUtil.set("data", "name", "Oli");
console.log(document.cookie); //data=name=Oli&book=JSON

删除cookie:

//若cookie为document.cookie=data=name=Oliver&book=jsbook;
document.cookie = "data" + "=" + "name" + "=" + "Oliver" + "&" + "book" + "=" + "jsbook";
//删除部份子cookie
SubCookieUtil.unset("data", "name");
console.log(document.cookie); //data=book=jsbook
//删除悉数cookie
SubCookieUtil.unsetAll("data");
console.log(document.cookie); //[This site has nos.]

举例:

多个提示banner的“不再提示功用”存在同一个cookie中

css部份:

  • {

    margin: 0;
    padding: 0;

    }

    div#message {

    border: 1px solid #ccc;
    background-color: #33CCFF;
    margin: 0;

    }

    p.content {

    color: white;
    font-size: 2em;
    margin: 0.3em;
    font-family: monospace;
    display: block;

    }

    a.notShow {

    width: 2em;
    display: block;
    float: right;

    }

dom部份:

<div id="message">
    <p class="content">welcome to my site!<a href="" class="notShow">shotdown</a></p>
    <p class="content">click to close this banner.<a href="" class="notShow">close</a></p>
</div>

js部份:

//猎取元素
var notShowBtn = document.getElementsByClassName("notShow");
//点击封闭按钮新建cookie并封闭banner
var notShowBtnList = [];
var hiddenElementCount = 0;

for (var i = 0, len = notShowBtn.length; i < len; i++) {
    notShowBtnList.push(i);
};

notShowBtnList.forEach(function(element, index) {
    notShowBtn[element].onclick = function() {
        event.preventDefault();
        var value = "content" + element;
        SubCookieUtil.set("hideMessage", value, "hide");
        notShowBtn[element].parentNode.style.display = "none";
    };
});

//搜检cookie当存在则封闭banner
window.onload = function() {
    notShowBtnList.forEach(function(element, index) {
        var value = "content" + element;
        if (SubCookieUtil.get("hideMessage", value)) {
            notShowBtn[element].parentNode.style.display = "none";
        }
    });
};

IE用户数据

用以下代码:

<div style="behavior:url(#default#userData)" id="dataStore"></div>

然后运用setAttribute()要领保留数据

再挪用save()要领保留到指定的数据空间

下一次页面载入后就能够运用load()要领读取数据

Web贮存机制

最初的Web Storage范例包含了两种对象的定义:sessionStorageglobalStorage,这两种都是在windows对象属性中存在的。

Storage范例

该范例供应最大的存储空间来存储名值对,有一下要领:

  • clear()删除一切值;

  • key(index)取得index处的名字;

  • getItem(name)依据指定的name猎取对应的值;

  • removeItem(name)删除name处的名值对;

  • setItem(name, value)为指定的name设置一个对应的值;

个中后三中能够直接挪用也能够经由过程Storage对象间接挪用。

还能够运用length属性来推断有若干名值对儿存放在Storage对象中,但没法推断对象中一切数据的大小,不过IE8供应了一个remainingSpace属性,用于猎取还能够运用的存储空间的字节数。

sessionStorage对象

sessionStorage对象存储特定于某个会话的数据,也就是该数据只坚持到该浏览器封闭。存储在sessionStorage中的数据能够逾越页面革新而存在,同时假如浏览器支撑,浏览器崩溃并重启今后依旧可用(Firefox和WebKit都支撑,IE则不可)。存储在sessionStorage中的数据只能由最初给定对象存储数据的页面接见到,所以对页面运用有限定。

存储数据

能够运用setItem()或许直接设置新的属性来存储数据。下面是这两种要领的例子。

sessionStorage.setItem("name", "Oliver"); //运用要领存储数据
sessionStorage.book = "JSON.com"; //运用属性存储数据

Firefox和Webkit完成了同步写入,所以增加到存储空间中的数据是马上被提交的。而IE的完成则是异步写入数据,所以在设置数据和将数据现实写入磁盘之间可能有一些耽误。

在IE8中能够强迫把数据写入磁盘:在设置新数据之前运用

  • begin()要领

而且一切设置完成今后挪用

  • commit()要领

看以下例子:

sessionStorage.begin();
sessionStorage.name = "oli";
sessionStorage.commit();

读取数据

  • getItem()

能够运用getItem()或许经由过程直接接见属性名来猎取数据。

sessionStorage.name = "oli";
sessionStorage.age = 18;
var val = sessionStorage.name;
var val_1 = sessionStorage.age;
console.log(val); //oli
console.log(val_1); //18

迭代数据

  • key()要领

经由过程连系length属性和key()要领来迭代sessionStorage中的值

for (var i = 0, len = sessionStorage.length; i < len; i++) {
    var key = sessionStorage.key(i);
    var val = sessionStorage.getItem(key);
    console.log(key + "=" + val);
};
  • for-in要领

还能够运用for-in轮回来迭代sessionStorage中的值:

for (key in sessionStorage) {
    var value = sessionStorage.getItem(key);
    console.log(key + "=" + value);
}

删除数据

  • removeItem()要领

要从sessionStorage中删除数据,能够运用delete操纵符删除对象属性,也可挪用removeItem()要领。

sessionStorage.name = "oli";
sessionStorage.age = 18;
sessionStorage.removeItem("name");
delete sessionStorage.age;

sessionStorage对象应当主要用于仅针对会话的小段数据的存储。

globalStorage对象(被localStorage对象庖代)

Firefox 2中完成了globalStorage对象。作为最初的Web Storage范例的一部份,这个对象的目标是逾越会话存储数据,但有特定的接见限定。要运用globalStorage,起首要指定哪些域能够接见该数据。能够经由过程方括号标记运用属性来完成,如以下例子所示。

globalStorage["test.com"].name = "Oliver";
var name = globalStorage["test.com"].name;

个中,globalStorage不是Storage的实例,globalStorage[“test.com”]才是

某些浏览器许可越发广泛的接见限定,比方只依据顶级域名举行限定或许许可全局接见,以下面例子所示:

//存储数据,任何人都能够接见——不要如许做!
globalStorage[""].name = "Nicholas";
//存储数据,能够让任何故.net末端域名接见——不要如许做!
globalStorage["net"].name = "Nicholas";

要防止运用这类可广泛接见的数据存储

对globalStorage空间的接见,是一句提议要求的页面的域名、协媾和端口来限定的。比方,假如运用HTTPS协定在w3cmm.com中存储了数据,那末经由过程HTTP接见的w3cmm.com的页面就不能接见该数据。

globalStorage的每一个属性都是Storage的实例。因而,能够像以下代码中如许运用。

globalStorage["www.test.com"].name = "Nicholas";
globalStorage["www.test.com"].book = "Professional JavaScript";
globalStorage["www.test.com"].removeItem("name");
var book = globalStorage["www.test.com"].getItem("book");

假如你事前不能肯定域名,那末运用location.host作为属性名比较平安。比方:

globalStorage[location.host].name = "Nicholas";
var book = globalStorage[location.host].getItem("book");

localStorage对象

localStorage对象在修订过的HTML5范例中作为耐久保留在客户端数据的计划庖代了globalStorage。要接见同一个localStorage对象,页面必需来自同一个域名(子域名无效),运用同一种协定,在同一个端口上。这相当于globalStorage[location.host]。

由于localStorage是Storage的实例,所以能够像运用sessionStorage一样来运用它。下面是一些例子。

localStorage.setItem("name", "Oliver");
localStorage.book = "JSON";
var book = localStorage.book;
var name = localStorage.getItem("name");
localStorage.removeItem("name");
delete localStorage.book;
localStorage.clear();

storage事宜

对Storage对象举行任何修正,都邑在文档上触发storage事宜。当经由过程属性或setItem()要领保留数据,运用delete操纵符或removeItem()删除数据,或着挪用clear()要领时,都邑发作该事宜。这个事宜的event对象有以下属性。

  • domain:发作变化的存储空间的域名。

  • key:设置或着删除的键名。

  • newValue:假如是设置值,则是新值;假如是删除键,则是null。

  • oldValue:键被变动之前的值。

以下代码:

var EventUtil = {
    addHandler: function(element, type, handler) {
        if (element.addEventListener) {
            element.addEventListener(type, handler, false);
        } else if (element.attachEvent) {
            element.attachEvent("on" + type, handler);
        } else {
            element["on" + type] = handler;
        }
    }
};
EventUtil.addHandler(document, "storage", function(event) {
    alert("Storage changed for " + event.domain);
});

限定

与别的客户端数据存储计划相似,Web Storage一样也有限定。这些限定因浏览器而异。平常来说,对存储空间大小的限定都是以每一个泉源(协定、域和端口)为单元的。

关于localStorage而言,大多数桌面浏览器会设置每一个泉源5MB的限定。Chrome和Safari对每一个泉源的限定是2.5MB。而ios版Safari和Android版Webkit的限定也是2.5MB

对sessionStorage的限定也是因浏览器而异。有的浏览器对sessionStorage的大小没有限定,但Chrome、Safari、ios版Safari和Android版Webkit都有限定,也都是2.5MB。IE8+和Opera对sessionStorage的限定是5MB

IndexedDB

引荐一篇文章运用 IndexedDB,来自MDN,链接地点:https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API/Using_IndexedDB

Indexed Database API 简称为IndexedDB,是在浏览器中保留构造化数据的一种数据库。

设想头脑是竖立一套API,轻易保留和读取JavaScript对象,同时还支撑查询和搜刮。

该操纵完全是异步举行的。

差不多每一次IndexedDB操纵,都须要注册onerror或onsuccess事宜处置惩罚顺序,以确保适当地处置惩罚效果。

在运用时须要加上浏览器供应商前缀:

var indexDB = window.indexedDB || window.msIndexedDB || window.mozIndexedDB || window.webkitIndexedDB;

翻开数据库

  • indexDB.open()

IndexedDB就是一个数据库,IndexedDB最大的特征是运用对象保留数据,而不是运用表来保留数据。

运用IndexedDB前起首要翻开它,即把要翻开的数据库名传给indexDB.open()。假如传入的数据库已存在,就会发送一个翻开它的要求;假如传入的数据库还不存在,就会发送一个竖立并翻开它的要求;

总之,挪用indexedDB.open()会返回一个IDBRequest对象,在这个对象上能够增加onerror和onsuccess事宜处置惩罚顺序。

var request, database;
request = indexedDB.open("Base");
request.onerror = function () {
    console.log(event.target.errorCode);
};
request.onsuccess = function () {
    database = event.target.result;
    console.log(event.target.result); //IDBDatabase {} 指向数据库实例对象
    console.log(event.target); //IDBOpenDBRequest {} 指向request对象
};
  • ABORT_ERR毛病码8 : A request was aborted,

  1. example, through a call to IDBTransaction.abort.

  • CONSTRAINT_ERR毛病码4 : A mutation operation in the transaction failed because a constraint was not satisfied.For example, an object, such as an object store or index, already exists and a request attempted to create a new one.

  • DATA_ERR毛病码5 : Data provided to an operation does not meet requirements.

  • NON_TRANSIENT_ERR毛病码2 : An operation was not allowed on an object.Unless the cause of the error is corrected, retrying the same operation would result in failure.

  • NOT_ALLOWED_ERR毛病码6 :
    An operation was called on an object where it is not allowed or at a time when it is not allowed.It also occurs

if a request is made on a source object that has been deleted or removed.

More specific variants of this error includes: TRANSACTION_INACTIVE_ERR and READ_ONLY_ERR.

  • NOT_FOUND_ERR毛病码3 : The operation failed because the requested database object could not be found;

  1. example, an object store did not exist but was being opened.

  • QUOTA_ERR毛病码11 : Either there ‘s not enough remaining storage space or the storage quota was reached and the user declined to give more space to the database.

  • READ_ONLY_ERR毛病码9 : A mutation operation was attempted in a READ_ONLY transaction.

  • TIMEOUT_ERR毛病码10 : A lock

  1. the transaction could not be obtained in a reasonable time.

  • TRANSACTION_INACTIVE_ERR毛病码7 : A request was made against a transaction that is either not currently active or is already finished.

  • UNKNOWN_ERR毛病码1 : The operation failed

  1. reasons unrelated to the database itself, and it is not covered by any other error code–

for example, a failure due to disk IO errors.

  • VER_ERR毛病码12 : A request to open a database with a version lower than the one it already has.This can only happen with IDBOpenDBRequest.

数据库版本号

  • indexedDB.setVersion()设置版本号

  • indexedDB.version猎取版本号

默许情况下,IndexedDB数据库是没有版本号的。最好一最先就挪用setVersion()要领为数据库指定一个版本号(传入一个示意版本号的字符串)。

如今就chrome浏览器,版本号要领已不再实用,别的,竖立database后chrome浏览器自动设置版本号为”1″:

var request, database;
request = indexedDB.open("Base");
request.onerror = function () {
    console.log(event.target.errorCode);
};
request.onsuccess = function () {
    database = event.target.result;
    console.log(database.setVersion); //undefined
    console.log(database.version); //1
};

要更新数据库的 schema,也就是竖立或许删除对象存储空间,须要完成 onupgradeneeded 处置惩罚顺序,这个处置惩罚顺序将会作为一个许可你处置惩罚对象存储空间的 versionchange 事件的一部份被挪用。

  • request.onupgradeneeded

如:

// 该事宜仅在较新的浏览器中被完成
request.onupgradeneeded = function(event) {
    // 更新对象存储空间和索引 .... 
};

如需设置数据库版本号,用下面要领:(旧)

var request, database;
request = indexedDB.open("Base");
request.onerror = function() {
    console.log(event.target.errorCode);
};
request.onsuccess = function() {
    database = event.target.result;
    if (database.version != "1.0") {
        request = database.setVersion("1.0");
        request.onerror = function() {
            console.log(event.target.errorCode);
        };
        request.onsuccess = function() {
            console.log("database name: " + database.name + "; version: " + database.version);
        };
    } else {
        console.log("database name: " + database.name + "; version: " + database.version); //database name: Base; version: 1
    };
};

竖立对象存储空间

竖立完数据库衔接今后,就要竖立对象存储空间。

键的供应能够有几种差别的要领,这取决于对象存储空间是运用 key path 照样 key generator

若要保留用户纪录由用户名、暗码构成,那末保留一条纪录的对象应当以下所示:

var userData = [{
    username: "007",
    firstName: "James",
    lastName: "Bond",
    password: "foo"
}, {
    username: "005",
    firstName: "Oliver",
    lastName: "Young",
    password: "boo"
}];

个中username为键(keyPath),这个应当是全局唯一的(代表一个user)。

下面是为了保留用户纪录而竖立对象存储空间的示例:

var request = indexedDB.open("Base", 2); //注重填写版本号
request.onerror = function() {
    console.log(event.target.errorCode);
};
request.onupgradeneeded = function() {
    var database = event.target.result;
    var store = database.createObjectStore("users", { keyPath: "username" }); //依据username竖立一个名为users的对象鸠合(表)
};

取得了对象存储空间的援用今后,就能够运用

向对象存储空间增加数据

  • add()put()要领向个中增加数据

这两个要领都吸收一个参数,即要保留的对象,然后这个对象就会被保留到存储空间中。

这两个要领的区分在于,假如空间中已包含了键值雷同的对象:add()会返回毛病;put()则会重写原有对象;

能够运用下面的代码初始化(add()要领)存储空间:

request.onupgradeneeded = function() {
    var database = event.target.result;
    var store = database.createObjectStore("users", { keyPath: "username" });
    for (var i in userData) {
        store.add(userData[i]);
    }
};

for-in轮回可用下面代码替代:

//users中保留着一批的用户对象
var i = 0,
    request, requests[], len = users.length;
while (i < len) {
    request = store.add(users[i++]);
    request.onerror = function() { // 毛病处置惩罚
    };
    request.onsuccess = function() { // 胜利
    };
    requests.push(request);
}

以下为完全的竖立数据库和存储空间以及初始化数据的代码例子:

//
//数据在这里userData
//
var userData = [{
    username: "007", //username唯一
    firstName: "James",
    lastName: "Bond",
    password: "foo"
}, {
    username: "005",
    firstName: "Oliver",
    lastName: "Young",
    password: "boo"
}];

//
//竖立数据库Alldata
//
var request = indexedDB.open("allData");
request.onerror = function() {
    console.log(event.target.errorCode);
};
request.onsuccess = function() {
    var database = event.target.result;
    console.log("数据库已竖立:" + database.name + "; 版本号:" + database.version);
};
//
//竖立存储空间(表)users,并初始化数据
//
var request = indexedDB.open("allData", 2);
request.onupgradeneeded = function() {
    var database = event.target.result;
    //竖立存储空间
    var store = database.createObjectStore("users", {
        keyPath: "username"
    });
    //增加数据
    for (var i in userData) {
        store.add(userData[i]);
    }
};

别的,下面是数据库构造:

indexedDB
    |-allData数据库
        |-users存储空间(表)
            |-(userData数据)

事件(读取、修正数据)

在数据库对象上挪用transaction()要领就能够竖立事件。任何时刻,想要读取或修正数据,都要经由过程事件来构造一切的操纵。

下面的代码保证只加载users存储空间中的数据,以便经由过程事件举行接见:

var transaction = database.transaction("users");

要接见多个对象存储空间,能够传入字符串数组:

var transaction = db.transaction(["users", "anotherStore"]);

上面的两个事件都是以只读的体式格局接见数据。要修正接见体式格局,必需在竖立事件时传入第二个参数。

接见形式

默许都是以只读的体式格局接见数据,要修正接见体式格局,必需传入第二个参数,这个参数示意接见形式:

  • READ_ONLY(0)示意只读;

  • READ_WRITE(1)示意读写;

  • VERSION_CHANGE(2)示意转变

注重: 旧版实验性的完成运用不提议运用的常量 IDBTransaction.READ_WRITE 而不是 “readwrite”。

所以如今平常示意读写应当传入字符串”readwrite”

个中,上面三个接见形式已被改成:

  • "readonly"只读;

  • "readwrite"读写;

以下:

var request = database.transaction("users", "readonly");

接见存储空间

  • objectStore()要领,并传入存储空间的称号,就能够接见特定的存储空间了。

就能够:

  • 运用add()和put()要领增加数据;

  • 运用get()能够取得值;

  • 运用delete()能够删除对象;

  • 运用clear()能够删除一切对象;

get()和delete()要领都吸收一个对象键作为参数。一切的这5个要领都邑返回一个新的要求对象。比方:

var request = database.transaction("users", "readonly").objectStore("users").get("007");
    request.onsuccess = function () {
        var result = event.target.result; //"James"
        console.log(result.firstName);
    };
    var request = database.transaction("users", "readwrite").objectStore("users").delete("005");

事件自身也有事宜处置惩罚顺序:onerroroncomplete

这两个事宜能够供应事件级的状况信息。

注重:经由过程oncomplete事宜的事宜对象接见不到get()要求返回的任何数据,必需在onsuccess事宜处置惩罚顺序中才接见到。

以下为实例:

var userData = [{
    username: "007", //username唯一
    firstName: "James",
    lastName: "Bond",
    password: "foo"
}, {
    username: "005",
    firstName: "Oliver",
    lastName: "Young",
    password: "boo"
}];



//竖立数据库Alldata
var request = indexedDB.open("allData");
request.onerror = function() {
    console.log(event.target.errorCode);
};
request.onsuccess = function() {
    var database = event.target.result;
    console.log("数据库已竖立:" + database.name + "; 版本号:" + database.version);
};
//竖立存储空间(表)users并初始化数据
var request = indexedDB.open("allData", 2);
var database;
request.onupgradeneeded = function() {
    database = event.target.result;
    //竖立存储空间
    var store = database.createObjectStore("users", {
        keyPath: "username"
    });
    //增加数据
    for (var i in userData) {
        store.add(userData[i]);
    }
};

var newPerson = {
    username: "001",
    firstName: "Troy",
    lastName: "Ruby",
    password: "hello"
};
//事件
var request = indexedDB.open("allData", 2);
request.onsuccess = function () {
    var database = event.target.result;
    // var request = database.transaction("users").objectStore("users").add(newPerson); //报错,由于只读,须要设置为"readwrite"
    var request = database.transaction("users", "readwrite").objectStore("users").add(newPerson);
    var request = database.transaction("users", "readonly").objectStore("users").get("007");
    request.onsuccess = function () {
        var result = event.target.result; //"James"
        console.log(result.firstName);
    };
    var request = database.transaction("users", "readwrite").objectStore("users").delete("005");
};

运用游标查询

游标就是指向效果集的一个指针,在对象存储空间上挪用;在须要检索多个对象的情况下,须要在事件内部竖立游标。注重,必需在事件内部竖立!

  • openCursor()要领能够竖立游标。

openCursor()要领返回的也是一个要求对象,也须要为该对象指定onsuccess和onerror事宜处置惩罚函数

var transaction = database.transaction("users", "readonly").objectStore("users").openCursor();

或许:

var store = db.transaction("users").objectStore("users"),
    request = store.openCursor();

request.onsuccess = function(event) {
    // 处置惩罚胜利
};
request.onerror = function(event) {
    // 处置惩罚失利
};

IDBCursor

在前面的onsuccess事宜处置惩罚顺序实行时,能够经由过程event.target.result取得存储空间中的下一个对象。

  • IDBCursor实例具有以下几个属性:

    • key: 对象的键;

    • value:现实的对象;

    • direction:数值,示意游标走动的方向。

      • 默许是IDBCursor.NEXT(0), 示意下一项。

      • IDBCursor.NEXT_TO_DUPLICATE(1), 示意下一个不反复的项;

      • IDBCursor.PREV(2)示意前一项;

      • IDBCursor.PREV_NO_DUPLICATE示意前一个不反复的项。

    • primaryKey:游标运用的键,有多是对象键,也有多是索引键(背面会议论索引)

检索效果信息

要检索某个信息的效果,以下代码:

var transaction = database.transaction("users", "readonly").objectStore("users").openCursor();
    transaction.onsuccess = function() {
        var cursor = event.target.result;
        if (cursor) {
            console.log(cursor); //IDBCursorWithValue {}direction: "next"key: "005"primaryKey: "005"source: IDBObjectStorevalue: Object__proto__: IDBCursorWithValue
            console.log(cursor.value); //Object {username: "005", firstName: "Oliver", lastName: "Young", password: "boo"}
            console.log(cursor.key); //005
            console.log("Key: " + cursor.key + "; Value: " + JSON.stringify(cursor.value)); //Key: 005; Value: {"username":"005","firstName":"Oliver","lastName":"Young","password":"boo"}
        }
    };

注重:返回的cursor.value是一个对象,必要时须要用到JSON.stringify要领

运用游标更新纪录

  • update()要领更新纪录

挪用update()要领能够运用指定的对象更新当前游标的value:

var transaction = database.transaction("users", "readwrite").objectStore("users").openCursor();
transaction.onsuccess = function() {
    var cursor = event.target.result;
    if (cursor) {
        if (cursor.key == "005") {
            console.log(cursor.value.firstName); //游标在第一个位置”005“所以他的firstName就是"Oliver"; 革新浏览器,显现的效果则为Oli
            var value = cursor.value; //变动当前游标所指的对象("005")的firstName为"Oli";
            value.firstName = "Oli";
            var updateRequest = cursor.update(value); //运用update要领要求保留更新
            updateRequest.onerror = function () {
                console.log(event.target.errorCode);
            };
            updateRequest.onsuccess = function () {
                console.log("success"); //success
            };
        }
    }
};
transaction.onerror = function() {
    console.log(event.target.errorCode);
};

运用游标删除纪录

  • delete()要领删除纪录

如:

var transaction = database.transaction("users", "readwrite").objectStore("users").openCursor();
transaction.onsuccess = function() {
    var cursor = event.target.result;
    if (cursor) {
        if (cursor.key == "005") {
            var deleteRequest = cursor.delete(); //要求删除此项
            deleteRequest.onerror = function () {
                // body...
            };
            deleteRequest.onsuccess = function () {
                // body...
            };
        }
    }
};

注重:假如当前的事件没有修正对象存储空间的权限,update()和delete()会抛出毛病。

挪动游标

默许情况下每一个游标只提议一次要求;要想提议另一次要求,必需挪用下面的一个要领:

  • continue(key): 挪动到效果集的下一项。参数key是可选的,不指定这个参数,游标挪动到下一项;指定这个参数的话,游标会挪动到指定键的位置。

  • advance(count): 向前挪动count指定的项数。

遍历

运用挪动游标的要领,能够用来遍历存储空间中的一切项:

var transaction = database.transaction("users", "readwrite").objectStore("users").openCursor();
transaction.onsuccess = function() {
    var cursor = event.target.result;
    if (cursor) {
        console.log("Key: " + cursor.key + "; Value: " + JSON.stringify(cursor.value));
        cursor.continue(); //挪动下一项
    } else {
        console.log("done");
    }
};

挪用continue()会触发另一次要求,进而再次挪用onsuccess处置惩罚顺序。假如没有更多项能够遍用时,event.target.result的值为null。

键局限

IDBKeyRange

键局限由IDBKeyRange的实例示意。

有四中定义键局限的体式格局:

only()要领:

var onlyrange = IDBKeyRange.only("007");
var transaction = database.transaction("users", "readwrite").objectStore("users").openCursor(onlyrange);

将onlyrange变量传入openCursor要领中

lowerBound()要领:

第二种定义键局限的要领是指定效果集的下界。下界示意游标最先的位置。

假如想要疏忽键为”007″的对象自身,从它的下一个对象最先,能够传入第二个参数true:

var lowerBound = IDBKeyRange.lowerBound("003", true); //第二个参数为true示意不包含003
var transaction = database.transaction("users", "readwrite").objectStore("users").openCursor(lowerBound);

upperBound()要领

第三种定义键局限的要领是指定效果集的上界,也就是指定游标不能超过哪一个键。

假如不想包含键为指定值的对象,一样传入第二个参数true:

var upperBound = IDBKeyRange.upperBound("005", true); //第二个参数为true示意不包含005
var transaction = database.transaction("users", "readwrite").objectStore("users").openCursor(upperBound);

bound()要领

运用bound()要领能够同时指定上下界。

这个要领能够吸收四个参数:示意下界的键,示意上界的键,可选的示意是不是跳过下界的布尔值和可选的示意是不是跳过上界的布尔值。

var bound = IDBKeyRange.bound("003", "005", true, false); //第三和第四个参数为true和false示意不包含003包含005
var transaction = database.transaction("users", "readwrite").objectStore("users").openCursor(bound);

设定游标方向

openCursor()能够吸收两个参数,一个是适才的IDBKeyRange实例,第二个是示意方向的数值常量,也就是前面讲到的IDBCursor中的常量。

一般情况下,游标都是从存储空间的第一项最先,挪用continue()或advance()行进到末了一项。游标的默许方向值是

  • IDBCursor.NEXTIDBCursor.NEXT_NO_DUPLICATE

  • IDBCursor.nextIDBCursor.nextunique

也能够竖立一个游标,从末了一个对象最先,逐一迭代,直到第一个对象,这时候要传入的常量是:

  • IDBCursor.PREVIDBCursor.PREV_NO_DUPLICATE

  • IDBCursor.prevIDBCursor.prevunique

索引

关于有些数据,须要竖立多个键,如把用户ID作为主键,以用户名竖立索引

竖立索引

起首援用对象存储空间,然后挪用

  • createIndex()要领

以下:

request.onupgradeneeded = function() {
    var database = event.target.result;
    var store = database.createObjectStore("users", {
        keyPath: "username"
    });
    for (var i in userData) {
        store.add(userData[i]);
    }
    var index = store.createIndex("firstName", "firstName", { unique: false }); //竖立名为firstName的索引,属性名为firstName,属性值非唯一
};

运用索引

  • index()要领

以下:

var index = database.transaction("users").objectStore("users").index("firstName");
console.log(index); //IDBIndex对象

索引上竖立游标

  • openCursor()要领

以下:

var request = index.openCursor();
request.onsuccess = function () {
    console.log(event.target.result); //IDBCursorWithValue对象
};

遍历:

var request = index.openCursor();
request.onsuccess = function() {
    var cursor = event.target.result; //IDBCursorWithValue对象
    if (cursor) {
        console.log(cursor.key + "; " + JSON.stringify(cursor.value));
        cursor.continue();
    } else {
        console.log("done");
    }
    // Alice; {
    //     "username": "003",
    //     "firstName": "Alice",
    //     "lastName": "Young",
    //     "password": "boo"
    // }
    // (index): 87 James; {
    //     "username": "007",
    //     "firstName": "James",
    //     "lastName": "Bond",
    //     "password": "foo"
    // }
    // (index): 87 Oliver; {
    //     "username": "005",
    //     "firstName": "Oliver",
    //     "lastName": "Young",
    //     "password": "boo"
    // }
    // (index): 90 done
};

索引上竖立主键的游标

  • openKeyCursor()要领

挪用这个特别的只返回每条纪录主键的游标,这个要领在event.result.key中保留索引键,在event.result.value中保留的则是主键,而不是悉数对象

索引中取得对象

  • get()要领

只需传入响应的索引键即可:

var store = db.transaction("users").objectStore("users");
var index = store.index("firstName");
var request = index.get("007");

依据索引键取得主键

  • getKey()要领

这个要领中event.result.value即是主键的值,而不是悉数对象:

var store = db.transaction("users").objectStore("users");
var index = store.index("firstName");
var request = index.getKey("007");

索引IDBIndex对象的属性

  • name:索引的名字

  • keyPath:createIndex要领中属性的途径

  • objectStore:索引的对象存储空间

  • unique:示意索引键是不是唯一

接见一切索引

  • indexNames属性

如:

var indexNames = store.indexNames;
for (var i = 0, len = store.indexNames.length; i < len; i++) {
    var index = store.index(indexNames[i]);
    console.log(index.name);
    //firstName
    //lastName
};

删除索引

  • deleteIndex()

如:

store.deleteIndex("firstName");

并发题目

每次翻开数据库,都应当指定onversionchange事宜处置惩罚顺序:

request.onsuccess = function() {
    database = event.target.result;
    database.onversionchange = function () {
        database.close();
    };
};

当设置version时,指定要求的onblocked事宜处置惩罚顺序也很主要:

var request = database.setVersion("2.0");
request.onblocked = function () {
    alert("轻先封闭其他标签页后再尝试");
};
request.onsuccess = function () {
    //处置惩罚胜利,继承
};

限定

  • 同源

  • 多个限定5MB大小

  • Firefox不许可当地接见IndexedDB

完全的例子

var userData = [{
    username: "007",
    firstName: "James",
    lastName: "Bond",
    password: "foo"
}, {
    username: "005",
    firstName: "Oliver",
    lastName: "Young",
    password: "boo"
}, {
    username: "003",
    firstName: "Alice",
    lastName: "Young",
    password: "boo"
}];

var newData = {
    username: "001",
    firstName: "Ali",
    lastName: "Bound",
    password: "hello"
};

var anotherNewData = {
    username: "001",
    firstName: "holyshit",
    lastName: "Bound",
    password: "hello"
};

var dbName = "allData",
    dbVersion = 1,
    dbStoreName = "users";

var db;

//初始化数据库
function initDb() {
    console.log("initDb..."); //初始化数据库...
    var req = indexedDB.open(dbName, dbVersion);
    req.onsuccess = function() {
        db = this.result;
        console.log("initDb Done.");
    };
    req.onerror = function() {
        console.log("initDb:", event.target.errorCode);
    };
    req.onupgradeneeded = function() {
        console.log("initDb.onupgradeneeded");
        var store = event.target.result.createObjectStore(dbStoreName, {
            keyPath: "username"
        }); //这里不能用db,而是event.target.result;
        store.createIndex("firstName", "firstName", {
            unique: false
        });
        store.createIndex("lastName", "lastName", {
            unique: false
        });
    };
}
initDb();

//增加数据
function addData(data) {
    console.log("add data...");
    var req = indexedDB.open(dbName, dbVersion);
    req.onsuccess = function() {
        var transaction = db.transaction(dbStoreName, "readwrite");
        var store = transaction.objectStore(dbStoreName);
        if (Object.prototype.toString.call(data).toString() === "[object Array]") {
            for (var i in data) {
                store.add(data[i]);
            }
        } else if (Object.prototype.toString.call(data).toString() === "[object Object]") {
            store.add(data);
        } else {
            console.log("adding data: please choose Array or Object.");
        }
    };
}
addData(userData);

//提取数据
function getData(key, callback) {
    console.log("get data...");
    var req = indexedDB.open(dbName, dbVersion);
    req.onsuccess = function() {
        var transaction = db.transaction(dbStoreName, "readonly");
        var store = transaction.objectStore(dbStoreName);
        var data = store.get(key);
        data.onsuccess = function() {
            var result = event.target.result;
            if (result) {
                callback(result);
                console.log("get data done.");
            }
        };
    };
}
// getData("003", function (result) {
//     console.log(result);
// });

//删除数据
function deleteData(key) {
    console.log("delete data...");
    var req = indexedDB.open(dbName, dbVersion);
    req.onsuccess = function() {
        var transaction = db.transaction(dbStoreName, "readwrite");
        var store = transaction.objectStore(dbStoreName);
        var data = store.delete(key);
        data.onsuccess = function() {
            console.log("delete data done.");
        };
    };
}
// deleteData("003");

//清空数据
function clearData() {
    console.log("delete data...");
    var req = indexedDB.open(dbName, dbVersion);
    req.onsuccess = function() {
        var transaction = db.transaction(dbStoreName, "readwrite");
        var store = transaction.objectStore(dbStoreName);
        var data = store.clear();
        data.onsuccess = function() {
            console.log("clear data done.");
        };
    };
}
// clearData();

//游标提取数据
function cursorGetData(key, callback) {
    console.log("cursor get data...");
    var req = indexedDB.open(dbName, dbVersion);
    req.onsuccess = function() {
        var transaction = db.transaction(dbStoreName, "readonly");
        var store = transaction.objectStore(dbStoreName);
        var cursor = store.openCursor();
        cursor.onsuccess = function() {
            var cursor = event.target.result;
            if (cursor.key !== key) {
                cursor.continue();
            } else {
                var result = cursor.value;
                callback(result);
                console.log("cursor get data done.");
            }
        };
    };
}
// cursorGetData("007", function (result) {
//     console.log(result);
// });

//游标修正数据
function cursorUpdateData(key, property, newValue) {
    console.log("cursor update data...");
    var req = indexedDB.open(dbName, dbVersion);
    req.onsuccess = function() {
        var transaction = db.transaction(dbStoreName, "readwrite");
        var store = transaction.objectStore(dbStoreName);
        var cursor = store.openCursor();
        cursor.onsuccess = function() {
            var cursor = event.target.result;
            if (cursor.key !== key) {
                cursor.continue();
            } else {
                var target = cursor.value;
                for (var i in target) {
                    if (i === property) {
                        var value = Object.defineProperty(target, property, {
                            value: newValue
                        });
                        var updateReq = cursor.update(value);
                        console.log("cursor update data done.");
                    }
                }
            }
        };
    };
}
// cursorUpdateData("003", "firstName", "Ali");

//游标删除数据
function cursorDeleteData(key) {
    console.log("cursor delete data...");
    var req = indexedDB.open(dbName, dbVersion);
    req.onsuccess = function() {
        var transaction = db.transaction(dbStoreName, "readwrite");
        var store = transaction.objectStore(dbStoreName);
        var cursor = store.openCursor();
        cursor.onsuccess = function() {
            var cursor = event.target.result;
            if (cursor.key !== key) {
                cursor.continue();
            } else {
                var deleteReq = cursor.delete();
                console.log("cursor delete data done.");
            }
        };
    };
}
// cursorDeleteData("003");

//游标遍历一切项
function cursorTraversalData(callback) {
    console.log("cursor tarversal data...");
    var req = indexedDB.open(dbName, dbVersion);
    var result = [];
    req.onsuccess = function() {
        var transaction = db.transaction(dbStoreName, "readonly");
        var store = transaction.objectStore(dbStoreName);
        var cursor = store.openCursor();
        cursor.onsuccess = function() {
            var cursor = event.target.result;
            if (cursor) {
                result.push(cursor.value);
                cursor.continue();
            } else {
                console.log("cursor traversal data done.");
                if (result.length > 0) {
                    callback(result);
                }
            }
        };
    };
}
// cursorTraversalData(function (result) {
//     for (var i in result) {
//         console.log(JSON.stringify(result[i]));
//     }
// });

//遍历局限内一切项
function boundTraversalData(lower, upper, boo1, boo2, callback) {
    console.log("bound tarversal data...");
    var req = indexedDB.open(dbName, dbVersion);
    var result = [];
    req.onsuccess = function() {
        var transaction = db.transaction(dbStoreName, "readonly");
        var store = transaction.objectStore(dbStoreName);
        var bound = IDBKeyRange.bound(lower, upper, boo1, boo2);
        var cursor = store.openCursor(bound);
        cursor.onsuccess = function() {
            var cursor = event.target.result;
            if (cursor) {
                result.push(cursor.value);
                cursor.continue();
            } else {
                console.log("bound traversal data done.");
                if (result.length > 0) {
                    callback(result);
                }
            }
        };
    };
}
// boundTraversalData("003", "007", true, true, function(result) {
//     for (var i in result) {
//         console.log(JSON.stringify(result[i]));
//     }
// });

//索引中取得对象
function indexGetData(index, key, callback) {
    console.log("index get data...");
    var req = indexedDB.open(dbName, dbVersion);
    req.onsuccess = function() {
        var transaction = db.transaction(dbStoreName, "readonly");
        var store = transaction.objectStore(dbStoreName);
        var target = store.index(index);
        var data = target.get(key);
        data.onsuccess = function() {
            var result = event.target.result;
            if (result) {
                callback(result);
                console.log("index get data done.");
            } else {
                console.log("index get data: error output.");
            }
        };
    };
}
// indexGetData("firstName", "Alice", function (result) {
//     console.log(result);
// });

//索引中取得主键
function indexGetKey(index, key, callback) {
    console.log("index get data...");
    var req = indexedDB.open(dbName, dbVersion);
    req.onsuccess = function() {
        var transaction = db.transaction(dbStoreName, "readonly");
        var store = transaction.objectStore(dbStoreName);
        var target = store.index(index);
        var data = target.getKey(key);
        data.onsuccess = function() {
            var result = event.target.result;
            if (result) {
                callback(result);
                console.log("index get key done.");
            } else {
                console.log("index get key: error output.");
            }
        };
    };
}
// indexGetKey("firstName", "Alice", function (result) {
//     console.log(result);
// });

//接见一切索引
function getAllIndex(callback) {
    console.log("get all index...");
    var req = indexedDB.open(dbName, dbVersion);
    req.onsuccess = function() {
        var transaction = db.transaction(dbStoreName, "readonly");
        var store = transaction.objectStore(dbStoreName);
        var indexNames = store.indexNames;
        if (indexNames.length) {
            for (var i = 0, len = store.indexNames.length; i < len; i++) {
                var index = store.index(indexNames[i]);
                callback(index);
            }
        }
    };
}
// getAllIndex(function (index) {
//     console.log(index.name);
//     console.log(index.keyPath);
//     console.log(index.objectStore.name);
//     console.log(index.unique);
// });
    原文作者:JS菌
    原文地址: https://segmentfault.com/a/1190000004609929
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞