澳门新浦京娱乐场网站-www.146.net-新浦京娱乐场官网
做最好的网站

主导使用,加载品质优化

Web应用中的离线数据存款和储蓄

2014/02/15 · HTML5, JavaScript · HTML5, Javascript

本文由 伯乐在线 - njuyz 翻译。未经许可,禁止转发!
英文出处:Nettuts 。迎接加入翻译组。

为了升高Web应用的用户体验,想必大多开拓者都会项目中引入离线数据存款和储蓄机制。然则面前碰着美妙绝伦的离线数据本事,哪一种才是最能满意项目须求的啊?本文将扶助各位找到最合适的那些。

H五 缓存机制浅析,移动端 Web 加载品质优化

2015/12/14 · HTML5 · IndexedDB, 性能, 移动前端

本文作者: 伯乐在线 - 腾讯bugly 。未经小编许可,禁止转发!
应接加入伯乐在线 专栏撰稿人。

深深剖判HTML5中的IndexedDB索引数据库,html伍indexeddb

那篇文章主要介绍了深入深入分析HTML5中的IndexedDB索引数据库,包涵事务锁等基本作用的连锁应用示例,要求的情侣能够参照下

介绍 IndexedDB是HTML5 WEB数据库,允许HTML5WEB应用在用户浏览器端存款和储蓄数据。对于使用来讲IndexedDB特别强劲、有用,能够在客户端的chrome,IE,Firefox等WEB浏览器中积累多量数量,下边简介一下IndexedDB的基本概念。
 
什么是IndexedDB IndexedDB,HTML伍新的数据存储,能够在客户端存款和储蓄、操作数据,能够使利用加载地越来越快,更加好地响应。它差异于关系型数据库,具备数据表、记录。它影响着大家设计和成立应用程序的秘籍。IndexedDB 创造有数据类型和轻易的JavaScript悠久对象的object,每种object能够有目录,使其立竿见影地询问和遍历整个群集。本文为你提供了什么样在Web应用程序中采取IndexedDB的安分守己事例。
 
开始 咱俩要求在实行前包蕴下前面置代码

JavaScript Code复制内容到剪贴板

  1. var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;   
  2.     
  3. //prefixes of window.IDB objects   
  4. var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;   
  5. var IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange   
  6.     
  7. if (!indexedDB) {   
  8. alert("Your browser doesn't support a stable version of IndexedDB.")   
  9. }  

 
打开IndexedDB 在创立数据库以前,大家首先要求为数据库创立数量,假如我们有如下的用户消息:

JavaScript Code复制内容到剪贴板

  1. var userData = [   
  2. { id: "1", name: "Tapas", age: 33, email: "[email protected]" },   
  3. { id: "2", name: "Bidulata", age: 55, email: "[email protected]" }   
  4. ];  

现今大家必要用open()方法张开大家的数据库:

JavaScript Code复制内容到剪贴板

  1. var db;   
  2. var request = indexedDB.open("databaseName", 1);   
  3.     
  4. request.onerror = function(e) {   
  5. console.log("error: ", e);   
  6. };   
  7.     
  8. request.onsuccess = function(e) {   
  9. db = request.result;   
  10. console.log("success: "  db);   
  11. };   
  12. request.onupgradeneeded = function(e) {   
  13.     
  14. }  

如上所示,大家已经开拓了名字为"databaseName",内定版本号的数据库,open()方法有五个参数:
1.率先个参数是数据库名称,它会检查实验名称叫"databaseName"的数据库是还是不是业已存在,倘诺存在则张开它,不然创制新的数据库。
贰.次之个参数是数据库的版本,用于用户更新数据库结构。
 
onSuccess处理 发出成功事件时“onSuccess”被触发,假使持有成功的伸手都在此管理,大家可以通过赋值给db变量保存请求的结果供之后选取。
 
onerror的管理程序 发生错误事件时“onerror”被触发,要是展开数据库的进度中倒闭。
 
Onupgradeneeded管理程序 若果你想翻新数据库(创立,删除或改造数据库),那么您不能够不贯彻onupgradeneeded管理程序,令你能够在数据库中做其余变动。 在“onupgradeneeded”管理程序中是足以改换数据库的布局的头一无二地点。
 
始建和丰硕数据到表:
IndexedDB使用对象存款和储蓄来积攒数据,而不是由此表。 每当八个值存款和储蓄在对象存款和储蓄中,它与3个键相关联。 它同意大家创造的别的对象存款和储蓄索引。 索引允许大家走访存储在指标存储中的值。 上面包车型客车代码呈现了何等创立对象存款和储蓄并插入预先筹划好的数额:

JavaScript Code复制内容到剪贴板

  1. request.onupgradeneeded = function(event) {   
  2. var objectStore = event.target.result.createObjectStore("users", {keyPath: "id"});   
  3. for (var i in userData) {   
  4. objectStore.add(userData[i]);    
  5. }   
  6. }  

笔者们利用createObjectStore()方法成立3个对象存储。 此方法接受多少个参数:

  • 积存的名号和参数对象。 在那边,我们有贰个名叫"users"的目的存款和储蓄,并定义了keyPath,那是指标唯一性的属性。 在此间,大家使用“id”作为keyPath,这些值在对象存款和储蓄中是头一无二的,大家务必确认保障该“ID”的习性在对象存款和储蓄中的每种对象中设有。 壹旦创造了指标存款和储蓄,我们得以起来运用for循环增添数据进去。
     
    手动将数据增加到表:
    大家得以手动增添额外的数量到数据库中。

JavaScript Code复制内容到剪贴板

  1. function Add() {   
  2. var request = db.transaction(["users"], "readwrite").objectStore("users")   
  3. .add({ id: "3", name: "Gautam", age: 30, email: "[email protected]" });   
  4.     
  5. request.onsuccess = function(e) {   
  6. alert("Gautam has been added to the database.");   
  7. };   
  8.     
  9. request.onerror = function(e) {   
  10. alert("Unable to add the information.");    
  11. }   
  12.     
  13. }  

在此以前我们在数据库中做其余的CRUD操作(读,写,修改),必须运用工作。 该transaction()方法是用来钦命大家想要举办事务管理的靶子存款和储蓄。 transaction()方法接受贰个参数(第三个和第多个是可选的)。 第二个是大家要拍卖的目的存储的列表,第一个钦定大家是不是要只读/读写,第11个是本子变化。
 
从表中读取数据 get()方法用于从目的存款和储蓄中搜寻数据。 大家前边早已安装对象的id作为的keyPath,所以get()方法将追寻具备一样id值的对象。 下边包车型大巴代码将赶回大家命名叫“Bidulata”的靶子:

JavaScript Code复制内容到剪贴板

  1. function Read() {   
  2. var objectStore = db.transaction(["users"]).objectStore("users");   
  3. var request = objectStore.get("2");   
  4. request.onerror = function(event) {   
  5. alert("Unable to retrieve data from database!");   
  6. };   
  7. request.onsuccess = function(event) {    
  8. if(request.result) {   
  9. alert("Name: "   request.result.name   ", Age: "   request.result.age   ", Email: "   request.result.email);   
  10. } else {   
  11. alert("Bidulata couldn't be found in your database!");    
  12. }   
  13. };   
  14. }  

 
从表中读取全体数据
上边包车型地铁方法寻找表中的全数数据。 这里咱们应用游标来搜寻对象存款和储蓄中的全体数据:

JavaScript Code复制内容到剪贴板

  1. function ReadAll() {   
  2. var objectStore = db.transaction("users").objectStore("users");    
  3. var req = objectStore.openCursor();   
  4. req.onsuccess = function(event) {   
  5. db.close();   
  6. var res = event.target.result;   
  7. if (res) {   
  8. alert("Key "   res.key   " is "   res.value.name   ", Age: "   res.value.age   ", Email: "   res.value.email);   
  9. res.continue();   
  10. }   
  11. };   
  12. req.onerror = function (e) {   
  13. console.log("Error Getting: ", e);   
  14. };    
  15. }  

该openCursor()用于遍历数据库中的多少个记录。 在continue()函数中承接读取下一条记下。
剔除表中的记录 上边包车型地铁法子从指标中除去记录。

JavaScript Code复制内容到剪贴板

  1. function Remove() {    
  2. var request = db.transaction(["users"], "readwrite").objectStore("users").delete("1");   
  3. request.onsuccess = function(event) {   
  4. alert("Tapas's entry has been removed from your database.");   
  5. };   
  6. }  

我们要将指标的key帕特h作为参数传递给delete()方法。
 
最终代码
上边包车型地铁情势从目的源中删除一条记下:

JavaScript Code复制内容到剪贴板

  1. <!DOCTYPE html>  
  2. <head>  
  3. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
  4. <title>IndexedDB</title>  
  5. <script type="text/javascript">  
  6. var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;   
  7.     
  8. //prefixes of window.IDB objects   
  9. var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;   
  10. var IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange   
  11.     
  12. if (!indexedDB) {   
  13. alert("Your browser doesn't support a stable version of IndexedDB.")   
  14. }   
  15. var customerData = [   
  16. { id: "1", name: "Tapas", age: 33, email: "[email protected]" },   
  17. { id: "2", name: "Bidulata", age: 55, email: "[email protected]" }   
  18. ];   
  19. var db;   
  20. var request = indexedDB.open("newDatabase", 1);   
  21.     
  22. request.onerror = function(e) {   
  23. console.log("error: ", e);   
  24. };   
  25.     
  26. request.onsuccess = function(e) {   
  27. db = request.result;   
  28. console.log("success: "  db);   
  29. };   
  30.     
  31. request.onupgradeneeded = function(event) {   
  32.     
  33. }   
  34. request.onupgradeneeded = function(event) {   
  35. var objectStore = event.target.result.createObjectStore("users", {keyPath: "id"});   
  36. for (var i in userData) {   
  37. objectStore.add(userData[i]);    
  38. }   
  39. }   
  40. function Add() {   
  41. var request = db.transaction(["users"], "readwrite")   
  42. .objectStore("users")   
  43. .add({ id: "3", name: "Gautam", age: 30, email: "[email protected]" });   
  44.     
  45. request.onsuccess = function(e) {   
  46. alert("Gautam has been added to the database.");   
  47. };   
  48.     
  49. request.onerror = function(e) {   
  50. alert("Unable to add the information.");    
  51. }   
  52.     
  53. }   
  54. function Read() {   
  55. var objectStore = db.transaction("users").objectStore("users");   
  56. var request = objectStore.get("2");   
  57. request.onerror = function(event) {   
  58. alert("Unable to retrieve data from database!");   
  59. };   
  60. request.onsuccess = function(event) {    
  61. if(request.result) {   
  62. alert("Name: "   request.result.name   ", Age: "   request.result.age   ", Email: "   request.result.email);   
  63. } else {   
  64. alert("Bidulata couldn't be found in your database!");    
  65. }   
  66. };   
  67. }   
  68. function ReadAll() {   
  69. var objectStore = db.transaction("users").objectStore("users");    
  70. var req = objectStore.openCursor();   
  71. req.onsuccess = function(event) {   
  72. db.close();   
  73. var res = event.target.result;   
  74. if (res) {   
  75. alert("Key "   res.key   " is "   res.value.name   ", Age: "   res.value.age   ", Email: "   res.value.email);   
  76. res.continue();   
  77. }   
  78. };   
  79. req.onerror = function (e) {   
  80. console.log("Error Getting: ", e);   
  81. };    
  82. }   
  83. function Remove() {    
  84. var request = db.transaction(["users"], "readwrite").objectStore("users").delete("1");   
  85. request.onsuccess = function(event) {   
  86. alert("Tapas's entry has been removed from your database.");   
  87. };   
  88. }   
  89. </script>  
  90. </head>  
  91.     
  92. <body>  
  93. <button onclick="Add()">Add record</button>  
  94. <button onclick="Remove()">Delete record</button>  
  95. <button onclick="Read()">Retrieve single record</button>  
  96. <button onclick="ReadAll()">Retrieve all records</button>  
  97. </body>  
  98. </html>  

localStorage是不带lock功用的。那么要促成前端的多中国少年共产党享并且须要lock功用那就须求选取任何本积累格局,比如indexedDB。indededDB使用的是事务管理的体制,那其实正是lock功效。
  做那几个测试须要先轻便的卷入下indexedDB的操作,因为indexedDB的连年比较麻烦,而且七个测试页面都亟待用到

JavaScript Code复制内容到剪贴板

  1. //db.js   
  2. //封装事务操作   
  3. IDBDatabase.prototype.doTransaction=function(f){   
  4.   f(this.transaction(["Obj"],"readwrite").objectStore("Obj"));   
  5. };   
  6. //连接数据库,成功后调用main函数   
  7. (function(){   
  8.   //张开数据库   
  9.   var cn=indexedDB.open("TestDB",1);   
  10.   //成立数量对象   
  11.   cn.onupgradeneeded=function(e){   
  12.     e.target.result.createObjectStore("Obj");   
  13.   };   
  14.   //数据库连接成功   
  15.   cn.onsuccess=function(e){   
  16.     main(e.target.result);   
  17.   };   
  18. })();   
  19.   接着是七个测试页面   
  20. <script src="db.js"></script>  
  21. <script>  
  22. //a.html   
  23. function main(e){   
  24.   (function callee(){   
  25.     //开首多少个思想政治工作   
  26.     e.doTransaction(function(e){   
  27.       e.put(1,"test"); //设置test的值为1   
  28.       e.put(2,"test"); //设置test的值为2   
  29.     });   
  30.     setTimeout(callee);   
  31.   })();   
  32. };   
  33. </script>  
  34. <script src="db.js"></script>  
  35. <script>  
  36. //b.html   
  37. function main(e){   
  38.   (function callee(){   
  39.     //开始三个作业   
  40.     e.doTransaction(function(e){   
  41.       //获取test的值   
  42.       e.get("test").onsuccess=function(e){   
  43.         console.log(e.target.result);   
  44.       };   
  45.     });   
  46.     setTimeout(callee);   
  47.   })();   
  48. };   
  49. </script>  

把localStorage换到了indexedDB事务管理。可是结果就分歧

澳门新浦京娱乐场网站 1

测试的时候b.html中恐怕不会应声有出口,因为indexedDB正忙着管理a.html东西,b.html事务丢在了作业丢队列中等待。然则无论如何,输出结果也不会是一以此值。因为indexedDB的纤维管理单位是事情,而不是localStorage这样以表明式为单位。那样假诺把lock和unlock之间需求管理的事物放入2个事情中就能够完成。此外,浏览器对indexedDB的支撑不比localStorage,所以利用时还得考虑浏览器包容。

那篇小说重要介绍了一语破的深入分析HTML5中的IndexedDB索引数据库,包含事务锁等基本功效的连带使...

indexedDB 基本选择

2017/12/14 · 基本功技能 · 1 评论 · IndexedDB

原稿出处: 党黎明澳门新浦京娱乐场网站,   


indexedDB简介:

indexedDB 是1种接纳浏览器存款和储蓄大批量数码的方法.它创造的数据能够被询问,并且能够离线使用.

 

indexedDB 有以下特点:

  1. indexedDBWebSQL 数据库的替代品
  2. indexedDB遵纪守法同源协议(只能访问同域中积存的数量,而不可能访问其余域的)
  3. API包含异步API同步API三种:繁多景况下采用异步API; 同步API必须同 WebWorkers 一齐使用, 目前从未有过浏览器帮助同步API
  4. indexedDB 是事情方式的数据库, 使用 key-value 键值对积存数据
  5. indexedDB 不接纳结构化查询语言(SQL). 它经过索引(index)所发生的指针(cursor)来达成查询操作

引言

乘胜HTML五的过来,各类Web离线数据技艺进入了开拓人士的视线。诸如AppCache、localStorage、sessionStorage和IndexedDB等等,每一种本事都有它们分别适用的层面。比方AppCache就相比吻合用来离线起动应用,大概在离线状态下使应用的一有的机能照常运作。接下来作者将会为大家作详细介绍,并且用部分代码片段来展现如何接纳这几个技能。

1 H五 缓存机制介绍

H5,即 HTML伍,是新一代的 HTML 典型,参预过多新的特色。离线存款和储蓄(也可称之为缓存机制)是内部一个相当关键的表征。H五引入的离线存款和储蓄,那意味 web 应用可举办缓存,并可在未曾因特网连接时开始展览访问。

H伍 应用程序缓存为利用带来八个优势:

  • 离线浏览 用户可在采取离线时行使它们
  • 进程 已缓存财富加载得更加快
  • 压缩服务器负载 浏览器将只从服务器下载更新过或改变过的财富。

依照标准,到近来结束,H伍 1共有陆种缓存机制,某些是从前已有,某个是 H5才新投入的。

  1. 浏览器缓存机制
  2. Dom Storgage(Web Storage)存款和储蓄机制
  3. Web SQL Database 存款和储蓄机制
  4. Application Cache(AppCache)机制
  5. Indexed Database (IndexedDB)
  6. File System API

上边大家先是解析各个缓存机制的规律、用法及特点;然后针对 Anroid 移动端 Web 质量加载优化的须要,看假若利用伏贴缓存机制来巩固 Web 的加载质量。


一、使用indexedDB的基本方式

  1. 开垦数据库并且初叶多少个作业。
  2. 创设1个 objecStore
  3. 构建一个伸手来施行一些数据库操作,像扩展或提取数额等。
  4. 透过监听正确类型的 DOM 事件以伺机操作完结。
  5. 在操作结果上开始展览局地操作(能够在 request 对象中找到)

AppCache

假让你的Web应用中有部分职能(大概全部应用)需求在退出服务器的景观下使用,那么就能够经过AppCache来让您的用户在离线状态下也能使用。你所需求做的就是创办二个布局文件,在中间钦定哪些能源供给被缓存,哪些无需。其余,仍可以够在里头内定有个别联机财富在脱机条件下的代表财富。

AppCache的布局文件一般是1个以.appcache最后的公文文件(推荐写法)。文件以CACHE MANIFEST伊始,包含下列叁部分剧情:

  • CACHE – 钦赐了怎么财富在用户率先次访问站点的时候需求被下载并缓存
  • NETWORK – 内定了哪些能源须要在同步条件下才具访问,这么些能源从不被缓存
  • FALLBACK – 钦点了上述能源在脱机条件下的替代财富

2 H五 缓存机制原理深入分析

2、创立、展开数据库

indexedDB 存在于全局对象window上, 它最根本的二个办法就是open措施, 该情势接收多个参数:

  • dbName // 数据库名称 [string]
  • version // 数据库版本 [整型number]

var DB_NAME = 'indexedDB-test', VERSION = 1, db; var request = indexedDB.open(DB_NAME, VEOdysseySION); request.onsuccess = function(event) { db = event.target.result; // console.log(event.target === request); // true db.onsuccess = function(event) { console.log('数据库操作成功!'); }; db.onerror = function(event) { console.error('数据库操作爆发错误!', event.target.errorCode); }; console.log('张开数据库成功!'); }; request.onerror = function(event) { console.error('创制数据库出错'); console.error('error code:', event.target.errorCode); }; request.onupgradeneeded = function(event) { // 更新目的存款和储蓄空间和目录 .... };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var DB_NAME = 'indexedDB-test', VERSION = 1, db;
var request = indexedDB.open(DB_NAME, VERSION);
request.onsuccess = function(event) {
    db = event.target.result;
    // console.log(event.target === request); // true
    db.onsuccess = function(event) {
        console.log('数据库操作成功!');
    };
    db.onerror = function(event) {
        console.error('数据库操作发生错误!', event.target.errorCode);
    };
    console.log('打开数据库成功!');
};
request.onerror = function(event) {
    console.error('创建数据库出错');
    console.error('error code:', event.target.errorCode);
};
request.onupgradeneeded = function(event) {
   // 更新对象存储空间和索引 ....
};

若果本域下不存在名叫DB_NAME的数据库,则上述代码会创立2个名叫DB_NAME、版本号为VERSION的数据库; 触发的轩然大波依次为: upgradeneededsuccess.

假如已存在名称为DB_NAME的数据库, 则上述代码会张开该数据库; 只触及success/error事件,不会触发upgradeneeded事件. db是对该数据库的引用.

示例

先是,你必要在页面上钦赐AppCache的布局文件:

XHTML

<!DOCTYPE html> <html manifest="manifest.appcache"> ... </html>

1
2
3
4
<!DOCTYPE html>
<html manifest="manifest.appcache">
...
</html>

在此处相对记得在劳务器端宣布上述配置文件的时候,需求将MIME类型设置为text/cache-manifest,不然浏览器不能符合规律分析。

接下去是开创在此以前定义好的种种能源。大家若是在那么些示例中,你付出的是1个相互类站点,用户能够在地方联系旁人并且揭橥斟酌。用户在离线的情事下仍旧能够访问网址的静态部分,而关系以及发布商议的页面则会被别的页面代替,无法访问。

好的,大家那就初叶定义那个静态资源:

JavaScript

CACHE MANIFEST CACHE: /about.html /portfolio.html /portfolio_gallery/image_1.jpg /portfolio_gallery/image_2.jpg /info.html /style.css /main.js /jquery.min.js

1
2
3
4
5
6
7
8
9
10
11
CACHE MANIFEST
 
CACHE:
/about.html
/portfolio.html
/portfolio_gallery/image_1.jpg
/portfolio_gallery/image_2.jpg
/info.html
/style.css
/main.js
/jquery.min.js

旁注:配置文件写起来有少数很不便于。举例来佛说,倘让你想缓存整个目录,你无法直接在CACHE部分行使通配符(*),而是只可以在NETWOMuranoK部分使用通配符把具有不应当被缓存的能源写出来。

你无需显式地缓存包括配置文件的页面,因为这几个页面会自动被缓存。接下来大家为挂钩和评价的页面定义FALLBACK部分:

JavaScript

FALLBACK: /contact.html /offline.html /comments.html /offline.html

1
2
3
FALLBACK:
/contact.html /offline.html
/comments.html /offline.html

末尾我们用二个通配符来阻止其他的财富被缓存:

JavaScript

NETWORK: *

1
2
NETWORK:
*

最终的结果正是下面那样:

JavaScript

CACHE MANIFEST CACHE: /about.html /portfolio.html /portfolio_gallery/image_1.jpg /portfolio_gallery/image_2.jpg /info.html /style.css /main.js /jquery.min.js FALLBACK: /contact.html /offline.html /comments.html /offline.html NETWORK: *

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CACHE MANIFEST
 
CACHE:
/about.html
/portfolio.html
/portfolio_gallery/image_1.jpg
/portfolio_gallery/image_2.jpg
/info.html
/style.css
/main.js
/jquery.min.js
 
FALLBACK:
/contact.html /offline.html
/comments.html /offline.html
 
NETWORK:
*

再有一件很注重的作业要记得:你的能源只会被缓存三回!也便是说,假若财富创新了,它们不会自动更新,除非你改改了安排文件。所以有二个至上实行是,在配备文件中追加一项版本号,每趟换代能源的时候顺便更新版本号:

JavaScript

CACHE MANIFEST # version 1 CACHE: ...

1
2
3
4
5
6
CACHE MANIFEST
 
# version 1
 
CACHE:
...

2.一 浏览器缓存机制

浏览器缓存机制是指通过 HTTP 协议头里的 Cache-Control(或 Expires)和 Last-Modified(或 Etag)等字段来支配文件缓存的建制。那应该是 WEB 中最早的缓存机制了,是在 HTTP 协议中落实的,有一些不相同于 Dom Storage、AppCache 等缓存机制,但实质上是同样的。能够知晓为,一个是讨论层达成的,七个是应用层实现的。

Cache-Control 用于调整文件在地头缓存有效时间长度。最布满的,比如服务器回包:Cache-Control:max-age=600 表示文件在本土应该缓存,且使得时长是600秒(从发出请求算起)。在接下去600秒内,如若有请求这么些能源,浏览器不会生出 HTTP 请求,而是径直利用本地缓存的文书。

Last-Modified 是标志文件在服务器上的最新更新时间。后一次恳请时,如若文件缓存过期,浏览器通过 If-Modified-Since 字段带上那些时刻,发送给服务器,由服务器比较时间戳来判断文件是或不是有更动。借使没有改变,服务器重返30肆报告浏览器继续使用缓存;假若有修改,则赶回200,同一时间再次回到最新的文书。

Cache-Control 经常与 Last-Modified 一同行使。三个用以调节缓存有效时间,几个在缓存失效后,向服务查询是或不是有革新。

Cache-Control 还只怕有一个同功效的字段:Expires。Expires 的值一个万万的时间点,如:Expires: Thu, 10 Nov 20一5 0八:45:1壹威他霉素T,表示在那一个时间点以前,缓存都是卓有成效的。

Expires 是 HTTP一.0 标准中的字段,Cache-Control 是 HTTP一.一标准中新加的字段,效率雷同,都以决定缓存的可行时间。当这些字段同期现身时,Cache-Control 是高优化级的。

Etag 也是和 Last-Modified 同样,对文本举行标志的字段。分化的是,Etag 的取值是2个对文本举行标记的风味字串。在向服务器查询文件是还是不是有更新时,浏览器通过 If-None-Match 字段把特色字串发送给服务器,由服务器和文件最新特征字串进行相称,来判断文件是不是有立异。未有创新回包30肆,有更新回包200。Etag 和 Last-Modified 可依照需求使用三个或三个同不时间利用。多个同有时候选用时,只要满意基中2个规则,就觉着文件并未有革新。

其它有二种独特的动静:

  • 手动刷新页面(F伍),浏览器会直接以为缓存已经过期(大概缓存还未曾过期),在呼吁中丰盛字段:Cache-Control:max-age=0,发包向服务器查询是不是有文件是不是有立异。
  • 强制刷新页面(Ctrl F五),浏览器会直接忽略本地的缓存(有缓存也会感到本地未有缓存),在央浼中加上字段:Cache-Control:no-cache(或 Pragma:no-cache),发包向服务重新拉取文件。

下边是由此 谷歌 Chrome 浏览器(用任何浏览器 抓包工具也得以)自带的开垦者工具,对3个财富文件分裂景况请求与回包的截图。

第叁回呼吁:200

澳门新浦京娱乐场网站 2

缓存限制期限内呼吁:200(from cache)

澳门新浦京娱乐场网站 3

缓存过期后呼吁:30四(Not Modified)

澳门新浦京娱乐场网站 4

诚如浏览器会将缓存记录及缓存文件存在本地 Cache 文件夹中。Android 下 App 借使选用 Webview,缓存的文书记录及文件内容会存在当前 app 的 data 目录中。

深入分析:Cache-Control 和 Last-Modified 一般用在 Web 的静态财富文件上,如 JS、CSS 和某个图像文件。通过安装能源文件缓存属性,对增高能源文件加载速度,节省流量很有意义,非常是运动互联网遭受。但难题是:缓存有效时间长度该怎么设置?假若设置太短,就起不到缓存的采纳;如若设置的太长,在财富文件有更新时,浏览器假使有缓存,则不能够即时取到最新的文书。

Last-Modified 供给向服务器发起查询请求,本领掌握能源文件有未有更新。就算服务器或许回到304报告未有立异,但也还应该有三个请求的经过。对于运动互联网,那些请求大概是相比耗时的。有一种说法叫“消灭30四”,指的正是优化掉30肆的请求。

抓包开掘,带 if-Modified-Since 字段的乞请,借使服务器回包30肆,回包带有 Cache-Control:max-age 或 Expires 字段,文件的缓存有效时间会更新,就是文件的缓存会重新有效。30肆回包后只要再请求,则又直白利用缓存文件了,不再向服务器查询文件是或不是更新了,除非新的缓存时间再一次过期。

其余,Cache-Control 与 Last-Modified 是浏览器内核的体制,一般都以标准的兑现,不能够改造或安装。以 QQ 浏览器的 X5为例,Cache-Control 与 Last-Modified 缓存不能够禁止使用。缓存体积是1贰MB,不分HOST,过期的缓存会初始被排除。假若都没过期,应该事先清最早的缓存或最快到期的或文件大小最大的;过期缓存也会有望依然有效的,清除缓存会形成财富文件的重新拉取。

还会有,浏览器,如 X5,在应用缓存文件时,是未曾对缓存文件内容举办校验的,那样缓存文件内容被改换的恐怕。

浅析发掘,浏览器的缓存机制还不是特别完美的缓存机制。完美的缓存机制应该是这样的:

  1. 缓存文件没更新,尽或许选用缓存,不用和服务器交互;
  2. 缓存文件有更新时,第不日常间能运用到新的公文;
  3. 缓存的文书要维持完整性,不行使被改变过的缓存文件;
  4. 缓存的容积大小要能设置或调节,缓存文件不能够因为存款和储蓄空间限制或超时被免去。
    以X5为例,第三、2条不能够而且知足,第二、四条都不能够知足。

在骨子里运用中,为了消除 Cache-Control 缓存时间长度倒霉设置的难题,以及为了”消灭30肆“,Web前端应用的秘诀是:

  1. 在要缓存的能源文件名中丰硕版本号或文件 MD5值字串,如 common.d5d0贰a0贰.js,common.v1.js,同期设置 Cache-Control:max-age=3153六千,也正是一年。在一年岁月内,能源文件假使本地有缓存,就能够采用缓存;也就不会有304的回包。
  2. 1旦财富文件有涂改,则更新文件内容,同期修改财富文件名,如 common.v二.js,html页面也会引用新的能源文件名。

通过这种艺术,完结了:缓存文件并未有立异,则应用缓存;缓存文件有更新,则第有时间使用新型文件的指标。即上面说的第贰、二条。第一、四条由于浏览器内部机制,近日还不能够知足。

3、成立对象存款和储蓄空间和目录

在关系型数据库(如mysql)中,一个数据库中会有多张表,每张表有独家的主键、索引等;

key-value型数据库(如indexedDB)中, 二个数据库会有七个目的存款和储蓄空间,每一种存款和储蓄空间有投机的主键、索引等;

创制对象存款和储蓄空间的操作一般位于创造数据库成功回调里:

request.onupgradeneeded = function(event) { // 更新指标存款和储蓄空间和目录 .... var database = event.target.result; var objectStore = database.createObjectStore("movies", { keyPath: "id" }); objectStore.createIndex('alt', 'alt', { unique: true }); objectStore.createIndex('title', 'title', { unique: false }); };

1
2
3
4
5
6
request.onupgradeneeded = function(event) { // 更新对象存储空间和索引 ....
    var database = event.target.result;
    var objectStore = database.createObjectStore("movies", { keyPath: "id" });
    objectStore.createIndex('alt', 'alt', { unique: true });
    objectStore.createIndex('title', 'title', { unique: false });
};

澳门新浦京娱乐场网站 5

onupgradeneeded 是大家唯一能够修改数据库结构的地点。当中,我们得以创制和删除对象存款和储蓄空间以及创设和删除索引。

在数据库对象database上,有以下措施可供调用:

  1. createObjectStore(storeName, configObj) 创制二个对象存款和储蓄空间
    • storeName // 对象存款和储蓄空间的名称 [string]
    • configObj // 该对象存款和储蓄空间的布置 [object] (个中的keyPath属性值,标记对象的该属性值唯一)
  2. createIndex(indexName, objAttr, configObj) 创制1个索引
    • indexName // 索引名称 [string]
    • objAttr // 对象的习性名 [string]
    • configObj // 该索引的布署对象 [object]

LocalStorage和SessionStorage

一经你想在Javascript代码里面保存些数据,那么那五个东西就派上用场了。前一个能够保存数据,永恒不会晚点(expire)。只倘诺同样的域和端口,全数的页面中都能访问到通过LocalStorage保存的多少。举个简单的事例,你可以用它来保存用户安装,用户能够把他的私家爱好保存在日前利用的微管理器上,现在展开应用的时候能够直接加载。后者也能保留数据,可是只要关闭浏览器窗口(译者注:浏览器窗口,window,假设是多tab浏览器,则此处指代tab)就失效了。而且那么些多少不能够在不一致的浏览器窗口之间共享,就算是在差异的窗口中做客同三个Web应用的别的页面。

旁注:有点亟需指示的是,LocalStorage和SessionStorage里面只好保留基本项指标数目,相当于字符串和数字类型。其余具备的数码能够透过各自的toString()方法转化后保存。要是您想保留3个对象,则必要使用JSON.stringfy方法。(借使这几个目的是七个类,你能够复写它暗许的toString()方法,那么些方法会自动被调用)。

贰.2 Dom Storage 存款和储蓄机制

DOM 存款和储蓄是1套在 Web Applications 1.0 标准中第1遍引进的与积累相关的天性的总称,今后壹度分离出来,单独发展变成独立的 W3C Web 存款和储蓄规范。 DOM 存储被设计为用来提供1个更大存款和储蓄量、更安全、更方便的蕴藏方法,从而得以代表掉将有些无需让服务器知道的音讯囤积到 cookies 里的这种价值观方式。

地方一段是对 Dom Storage 存款和储蓄机制的合法公布。看起来,Dom Storage 机制就像是 Cookies,但有一点点优势。

Dom Storage 是经过存款和储蓄字符串的 Key/Value 对来提供的,并提供 5MB (分化浏览器可能两样,分 HOST)的储存空间(Cookies 才 4KB)。别的 Dom Storage 存款和储蓄的数目在本地,不像 Cookies,每便请求一次页面,Cookies 都会发送给服务器。

DOM Storage 分为 sessionStorage 和 localStorage。localStorage 对象和 sessionStorage 对象使用办法基本一样,它们的区分在于功用的限量不一。sessionStorage 用来存储与页面相关的数额,它在页面关闭后不可能运用。而 localStorage 则长久存在,在页面关闭后也得以接纳。

Dom Storage 提供了以下的储存接口:

XHTML

interface Storage { readonly attribute unsigned long length; [IndexGetter] DOMString key(in unsigned long index); [NameGetter] DOMString getItem(in DOMString key); [NameSetter] void setItem(in DOMString key, in DOMString data); [NameDeleter] void removeItem(in DOMString key); void clear(); };

1
2
3
4
5
6
7
8
interface Storage {
readonly attribute unsigned long length;
[IndexGetter] DOMString key(in unsigned long index);
[NameGetter] DOMString getItem(in DOMString key);
[NameSetter] void setItem(in DOMString key, in DOMString data);
[NameDeleter] void removeItem(in DOMString key);
void clear();
};

sessionStorage 是个全局对象,它爱慕着在页面会话(page session)时期有效的贮存空间。只要浏览器开着,页面会话周期就能够直接不断。当页面重新载入(reload)大概被还原(restores)时,页面会话也是间接存在的。每在新标签可能新窗口中开采二个新页面,都会开头化3个新的对话。

XHTML

<script type="text/javascript"> // 当页面刷新时,从sessionStorage复苏此前输入的内容 window.onload = function(){ if (window.sessionStorage) { var name = window.sessionStorage.getItem("name"); if (name != "" || name != null){ document.getElementById("name").value = name; } } }; // 将数据保存到sessionStorage对象中 function saveToStorage() { if (window.sessionStorage) { var name = document.getElementById("name").value; window.sessionStorage.setItem("name", name); window.location.href="session_storage.html"; } } </script> <form action="./session_storage.html"> <input type="text" name="name" id="name"/> <input type="button" value="Save" onclick="saveToStorage()"/> </form>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<script type="text/javascript">
// 当页面刷新时,从sessionStorage恢复之前输入的内容
window.onload = function(){
    if (window.sessionStorage) {
        var name = window.sessionStorage.getItem("name");
        if (name != "" || name != null){
            document.getElementById("name").value = name;
         }
     }
};
 
// 将数据保存到sessionStorage对象中
function saveToStorage() {
    if (window.sessionStorage) {
        var name = document.getElementById("name").value;
        window.sessionStorage.setItem("name", name);
        window.location.href="session_storage.html";
     }
}
</script>
 
<form action="./session_storage.html">
    <input type="text" name="name" id="name"/>
    <input type="button" value="Save" onclick="saveToStorage()"/>
</form>

当浏览器被意外刷新的时候,一些如今数据应当被保存和回复。sessionStorage 对象在拍卖这种处境的时候是最得力的。举个例子恢复生机大家在表单中曾经填写的数量。

把上面包车型客车代码复制到 session_storage.html(也能够从附件中从来下载)页面中,用 谷歌 Chrome 浏览器的例外 PAGE 或 WINDOW 张开,在输入框中分别输入分裂的文字,再点击“Save”,然后分别刷新。每个PAGE 或 WINDOW 呈现都是当下PAGE输入的剧情,互不影响。关闭 PAGE,再另行打开,上三遍输入保存的内容早已远非了。

澳门新浦京娱乐场网站 6

澳门新浦京娱乐场网站 7

Local Storage 的接口、用法与 Session Storage 同样,唯一不一样的是:Local Storage 保存的数量是持久性的。当前 PAGE 关闭(Page Session 甘休后),保存的数目依旧存在。重新张开PAGE,上次封存的数码足以赢得到。此外,Local Storage 是全局性的,同不时间开垦多个 PAGE 会共享壹份存多少,在贰个PAGE中期维修改数据,另三个 PAGE 中是能够感知到的。

XHTML

<script> //通过localStorage直接引用key, 另1种写法,等价于: //localStorage.getItem("pageLoadCount"); //localStorage.setItem("pageLoadCount", value); if (!localStorage.pageLoadCount) localStorage.pageLoadCount = 0; localStorage.pageLoadCount = parseInt(localStorage.pageLoadCount) 1; document.getElementById('count').textContent = localStorage.pageLoadCount; </script> <p> You have viewed this page <span id="count">an untold number of</span> time(s). </p>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>
  //通过localStorage直接引用key, 另一种写法,等价于:
  //localStorage.getItem("pageLoadCount");
  //localStorage.setItem("pageLoadCount", value);
  if (!localStorage.pageLoadCount)
localStorage.pageLoadCount = 0;
     localStorage.pageLoadCount = parseInt(localStorage.pageLoadCount) 1;
     document.getElementById('count').textContent = localStorage.pageLoadCount;
</script>
 
<p>
    You have viewed this page
    <span id="count">an untold number of</span>
    time(s).
</p>

将地点代码复制到 local_storage.html 的页面中,用浏览器展开,pageLoadCount 的值是壹;关闭 PAGE 重新张开,pageLoadCount 的值是贰。那是因为第二回的值已经保存了。

澳门新浦京娱乐场网站 8

澳门新浦京娱乐场网站 9

用八个 PAGE 相同的时间开垦 local_storage.html,并分别轮流刷新,开掘八个 PAGE 是共享多个 pageLoadCount 的。

澳门新浦京娱乐场网站 10

澳门新浦京娱乐场网站 11

解析:Dom Storage 给 Web 提供了一种更录活的数额存款和储蓄格局,存款和储蓄空间更加大(相对Cookies),用法也相比较简单,方便存款和储蓄服务器或地点的有的不经常数据。

从 DomStorage 提供的接口来看,DomStorage 适合积累相比较轻巧的多少,假设要存款和储蓄结构化的多少,大概要依赖JASON了,将在存款和储蓄的对象转为 JASON 字串。不太适合积累比较复杂或存储空间供给非常大的数量,也不相符积存静态的文件等。

在 Android 内嵌 Webview 中,须要通过 Webview 设置接口启用 Dom Storage。

XHTML

WebView myWebView = (WebView) findViewById(R.id.webview); WebSettings webSettings = myWebView.getSettings(); webSettings.setDomStorageEnabled(true);

1
2
3
WebView myWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setDomStorageEnabled(true);

拿 Android 类比的话,Web 的 Dom Storage 机制就好像于 Android 的 SharedPreference 机制。

四、增加和删除数据

对数据库的操作(增删查改等)都要求通过事务来完成,事务抱有三种形式:

  • readonly 只读(能够并发进行,优先接纳)
  • readwrite 读写
  • versionchange 版本改换

示例

咱俩不要紧来看看后边的事例。在联系人和钻探的片段,大家得以每一日保存用户输入的东西。那样1来,纵然用户不小心关闭了浏览器,以前输入的东西也不会丢掉。对于jQuery来讲,这一个成效是小菜壹碟。(注意:表单中各类输入字段都有id,在此处大家就用id来替代具体的字段)

JavaScript

$('#comments-input, .contact-field').on('keyup', function () { // let's check if localStorage is supported if (window.localStorage) { localStorage.setItem($(this).attr('id'), $(this).val()); } });

1
2
3
4
5
6
$('#comments-input, .contact-field').on('keyup', function () {
   // let's check if localStorage is supported
   if (window.localStorage) {
      localStorage.setItem($(this).attr('id'), $(this).val());
   }
});

历次提交联系人和商量的表单,大家须要清空缓存的值,大家得以如此管理提交(submit)事件:

JavaScript

$('#comments-form, #contact-form').on('submit', function () { // get all of the fields we saved $('#comments-input, .contact-field').each(function () { // get field's id and remove it from local storage localStorage.removeItem($(this).attr('id')); }); });

1
2
3
4
5
6
7
$('#comments-form, #contact-form').on('submit', function () {
   // get all of the fields we saved
   $('#comments-input, .contact-field').each(function () {
      // get field's id and remove it from local storage
      localStorage.removeItem($(this).attr('id'));
   });
});

终极,每一遍加载页面包车型客车时候,把缓存的值填充到表单上就能够:

JavaScript

// get all of the fields we saved $('#comments-input, .contact-field').each(function () { // get field's id and get it's value from local storage var val = localStorage.getItem($(this).attr('id')); // if the value exists, set it if (val) { $(this).val(val); } });

1
2
3
4
5
6
7
8
9
// get all of the fields we saved
$('#comments-input, .contact-field').each(function () {
   // get field's id and get it's value from local storage
   var val = localStorage.getItem($(this).attr('id'));
   // if the value exists, set it
   if (val) {
      $(this).val(val);
   }
});

2.三 Web SQL Database存款和储蓄机制

H伍 也提供基于 SQL 的数据仓库储存款和储蓄机制,用于存款和储蓄适合数据库的结构化数据。依照官方的科班文档,Web SQL Database 存储机制不再推荐应用,今后也不再维护,而是推荐使用 AppCache 和 IndexedDB。

近期主流的浏览器(点击查看浏览器帮衬景况)都还是帮助 Web SQL Database 存款和储蓄机制的。Web SQL Database 存款和储蓄机制提供了1组 API 供 Web App 创设、存款和储蓄、查询数据库。

上面通过轻易的例证,演示下 Web SQL Database 的采用。

XHTML

<script> if(window.openDatabase){ //张开数据库,假如未有则创设 var db = openDatabase('mydb', '一.0', 'Test DB', 二 * 10二四); //通过事务,创设三个表,并增加两条记下 db.transaction(function (tx) { tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)'); tx.executeSql('INSERT INTO LOGS (id, log) VALUES (壹, "foobar")'); tx.executeSql('INSERT INTO LOGS (id, log) VALUES (贰, "logmsg")'); }); //查询表中存有记录,并突显出来 db.transaction(function (tx) { tx.executeSql('SELECT * FROM LOGS', [], function (tx, results) { var len = results.rows.length, i; msg = "<p>Found rows: " len "</p>"; for(i=0; i<len; i ){ msg = "<p>" results.rows.item(i).log "</p>"; } document.querySelector('#status').innerHTML = msg; }, null); }); } </script> <div id="status" name="status">Status Message</div>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<script>
    if(window.openDatabase){
      //打开数据库,如果没有则创建
      var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024);
 
       //通过事务,创建一个表,并添加两条记录
      db.transaction(function (tx) {
           tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)');
           tx.executeSql('INSERT INTO LOGS (id, log) VALUES (1, "foobar")');
           tx.executeSql('INSERT INTO LOGS (id, log) VALUES (2, "logmsg")');
       });
 
      //查询表中所有记录,并展示出来
     db.transaction(function (tx) {
         tx.executeSql('SELECT * FROM LOGS', [], function (tx, results) {
             var len = results.rows.length, i;
             msg = "<p>Found rows: " len "</p>";
             for(i=0; i<len; i ){
                 msg = "<p>" results.rows.item(i).log "</p>";
             }
             document.querySelector('#status').innerHTML =  msg;
             }, null);
      });
}
 
</script>
 
<div id="status" name="status">Status Message</div>

将上边代码复制到 sql_database.html 中,用浏览器展开,可观察上面包车型大巴剧情。

澳门新浦京娱乐场网站 12

官方提出浏览器在落到实处时,对各种 HOST 的数据仓库储存款和储蓄空间作早晚范围,建议私下认可是 5MB(分 HOST)的分配的定额;达到上限后,能够报名更加的多存储空间。别的,今后主流浏览器 SQL Database 的贯彻都是根据 SQLite。

深入分析:SQL Database 的机要优势在于能够存款和储蓄结构复杂的数据,能丰盛利用数据库的优势,可方便对数据开始展览追加、删除、修改、查询。由于 SQL 语法的纷纭,使用起来麻烦一些。SQL Database 也不太适合做静态文件的缓存。

在 Android 内嵌 Webview 中,须要通过 Webview 设置接口启用 SQL Database,同有难题候还要设置数据库文件的贮存路线。

XHTML

WebView myWebView = (WebView) findViewById(R.id.webview); WebSettings webSettings = myWebView.getSettings(); webSettings.setDatabaseEnabled(true); final String dbPath = getApplicationContext().getDir("db", Context.MODE_PRIVATE).getPath(); webSettings.setDatabasePath(dbPath);

1
2
3
4
5
WebView myWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setDatabaseEnabled(true);
final String dbPath = getApplicationContext().getDir("db", Context.MODE_PRIVATE).getPath();
webSettings.setDatabasePath(dbPath);

Android 系统也利用了汪洋的数据库用来积攒数据,举例联系人、短音讯等;数据库的格式也 SQLite。Android 也提供了 API 来操作 SQLite。Web SQL Database 存款和储蓄机制固然经过提供壹组 API,借助浏览器的贯彻,将这种 Native 的机能提要求了 Web App。

向数据库中追扩充少

前面提到,扩充数量要求通过事务事务的行使格局如下:

var transaction = db.transaction(['movies'], 'readwrite'); transaction.oncomplete = function(event) { console.log('事务落成!'); }; transaction.onerror = function(event) { console.log('事务失利!', event.target.errorCode); }; transaction.onabort = function(event) { console.log('事务回滚!'); };

1
2
3
4
5
6
7
8
9
10
var transaction = db.transaction(['movies'], 'readwrite');
transaction.oncomplete = function(event) {
    console.log('事务完成!');
};
transaction.onerror = function(event) {
    console.log('事务失败!', event.target.errorCode);
};
transaction.onabort = function(event) {
    console.log('事务回滚!');
};

澳门新浦京娱乐场网站 13数据库对象的transaction()办法接收八个参数:

  • storeNames // 对象存款和储蓄空间,能够是目的存款和储蓄空间名称的数组,也足以是单个对象存款和储蓄空间名称,必传 [array|string]
  • mode // 事务形式,上边提到的二种之壹,可选,暗中认可值是readonly [string]

那般,大家收获1个政工对象transaction, 有三种事件可能会被触发: complete, error, abort. 现在,大家通过作业向数据库indexedDB-test的 对象存款和储蓄空间movies中插入数据:

var objectStore = transaction.objectStore('movies'); // 钦命对象存款和储蓄空间 var data = [{ "title": "寻梦环游记", "year": "20一七", "alt": "", "id": "20495023" }, { "title": "你在哪", "year": "2016", "alt": "", "id": "2663903三" }, { "title": "笔仙咒怨", "year": "20①柒", "alt": "", "id": "27054612" }]; data.forEach(function(item, index){ var request = objectStore.add(item); request.onsuccess = function(event) { console.log('插入成功!', index); console.log(event.target.result, item.id); // add()方法调用成功后result是被加多的值的键(id) }; });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var objectStore = transaction.objectStore('movies');  // 指定对象存储空间
var data = [{
  "title": "寻梦环游记",
  "year": "2017",
  "alt": "https://movie.douban.com/subject/20495023/",
  "id": "20495023"
}, {
  "title": "你在哪",
  "year": "2016",
  "alt": "https://movie.douban.com/subject/26639033/",
  "id": "26639033"
}, {
  "title": "笔仙咒怨",
  "year": "2017",
  "alt": "https://movie.douban.com/subject/27054612/",
  "id": "27054612"
}];
data.forEach(function(item, index){
    var request = objectStore.add(item);
    request.onsuccess = function(event) {
        console.log('插入成功!', index);
        console.log(event.target.result, item.id); // add()方法调用成功后result是被添加的值的键(id)
    };
});

澳门新浦京娱乐场网站 14

经过职业对象transaction,在objectStore()主意中钦定对象存款和储蓄空间,就赢得了足以对该指标存款和储蓄空间拓展操作的目的objectStore.

向数据库中增添数量,add()主意增添的对象,若是数据库中已存在同样的主键,也许唯1性索引的键值重复,则该条数据不会插入进去;

日加多少还也可能有一个办法: put(), 使用方法和add()分歧之处在于,数据库中若存在同样主键只怕唯一性索引重复,则会更新该条数据,不然插入新数据。

IndexedDB

在本身个人看来,那是最风趣的一种技艺。它能够保存大批量透过索引(indexed)的数目在浏览器端。这样1来,就能够在客户端保存复杂对象,大文书档案等等数据。而且用户能够在离线意况下访问它们。那1特点差非常少适用于具备品类的Web应用:要是您写的是邮件客户端,你能够缓存用户的邮件,以供稍后再看;假若你写的是相册类应用,你能够离线保存用户的肖像;纵然你写的是GPS导航,你能够缓存用户的不2秘诀……不计其数。

IndexedDB是二个面向对象的数据库。那就表示在IndexedDB中既不存在表的概念,也从没SQL,数据是以键值对的花样保留的。在那之中的键既能够是字符串和数字等基础项目,也足以是日期和数组等复杂类型。那一个数据库本人构建于积累(store,二个store类似于关系型数据中表的定义)的功底上。数据库中各类值都不可能不要有对应的键。各个键既能够自动生成,也能够在插入值的时候钦命,也能够取自于值中的有些字段。假诺您调节利用值中的字段,那么只可以向当中增添Javascript对象,因为基础数据类型不像Javascript对象那样有自定义属性。

2.4 Application Cache 机制

Application Cache(简称 AppCache)就如是为支撑 Web App 离线使用而开拓的缓存机制。它的缓存机制就好像于浏览器的缓存(Cache-Control 和 Last-Modified)机制,都是以文件为单位开始展览缓存,且文件有肯定创新机制。但 AppCache 是对浏览器缓存机制的补给,不是顶替。

先拿 W3C 官方的二个例子,说下 AppCache 机制的用法与功力。

XHTML

<!DOCTYPE html> <html manifest="demo_html.appcache"> <body> <script src="demo_time.js"></script> <p id="timePara"><button onclick="getDateTime()">Get Date and Time</button></p> <p><img src="img_logo.gif" width="336" height="69"></p> <p>Try opening <a href="tryhtml5_html_manifest.htm" target="_blank">this page</a>, then go offline, and reload the page. The script and the image should still work.</p> </body> </html>

1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html manifest="demo_html.appcache">
<body>
 
<script src="demo_time.js"></script>
 
<p id="timePara"><button onclick="getDateTime()">Get Date and Time</button></p>
<p><img src="img_logo.gif" width="336" height="69"></p>
<p>Try opening <a href="tryhtml5_html_manifest.htm" target="_blank">this page</a>, then go offline, and reload the page. The script and the image should still work.</p>
 
</body>
</html>

上边 HTML 文书档案,引用外部三个 JS 文件和多个 GIF 图片文件,在其 HTML 头中通过 manifest 属性引用了2个 appcache 结尾的文书。

笔者们在 谷歌(Google) Chrome 浏览器中开垦那一个 HTML 链接,JS 功效符合规律,图片也出示不奇怪。禁止使用网络,关闭浏览注重新张开那个链接,开采 JS 工作健康,图片也显得寻常。当然也许有十分的大只怕是浏览缓存起的功效,我们得以在文书的浏览器缓存过期后,禁止使用网络再试,发现HTML 页面也是寻常的。

经过 谷歌 Chrome 浏览器自带的工具,大家得以查阅已经缓存的 AppCache(分 HOST)。

澳门新浦京娱乐场网站 15

下面截图中的缓存,就是大家刚刚张开 HTML 的页面 AppCache。从截图中看,HTML 页面及 HTML 引用的 JS、GIF 图像文件都被缓存了;其它 HTML 头中 manifest 属性引用的 appcache 文件也缓存了。

AppCache 的法则有多少个关键点:manifest 属性和 manifest 文件。

HTML 在头中通过 manifest 属性引用 manifest 文件。manifest 文件,就是地点以 appcache 结尾的文书,是三个习认为常文书文件,列出了亟待缓存的公文。

澳门新浦京娱乐场网站 16

地点截图中的 manifest 文件,就 HTML 代码引用的 manifest 文件。文件相比较轻易,第壹行是重要字,第壹、3行就是要缓存的文本路线(相对路线)。那只是最轻松易行的 manifest 文件,完整的还包蕴别的重要字与内容。引用 manifest 文件的 HTML 和 manifest 文件中列出的要缓存的文书最后都会被浏览器缓存。

完全的 manifest 文件,包含四个 Section,类型 Windows 中 ini 配置文件的 Section,可是并非中括号。

  1. CACHE MANIFEST – Files listed under this header will be cached after they are downloaded for the first time
  2. NETWORK – Files listed under this header require a connection to the server, and will never be cached
  3. FALLBACK – Files listed under this header specifies fallback pages if a page is inaccessible

完整的 manifest 文件,如:

XHTML

CACHE MANIFEST # 2012-02-21 v1.0.0 /theme.css /logo.gif /main.js NETWORK: login.asp FALLBACK: /html/ /offline.html

1
2
3
4
5
6
7
8
9
10
11
CACHE MANIFEST
# 2012-02-21 v1.0.0
/theme.css
/logo.gif
/main.js
 
NETWORK:
login.asp
 
FALLBACK:
/html/ /offline.html

总的来讲,浏览器在第二回加载 HTML 文件时,会深入分析 manifest 属性,并读取 manifest 文件,获取 Section:CACHE MANIFEST 下要缓存的文件列表,再对文本缓存。

AppCache 的缓存文件,与浏览器的缓存文件分别储存的,依旧壹份?应该是分开的。因为 AppCache 在本土也会有 ⑤MB(分 HOST)的空中限制。

AppCache 在第壹回加载生成后,也许有更新机制。被缓存的文本假如要立异,须求立异manifest 文件。因为浏览器在后一次加载时,除了会暗中同意使用缓存外,还有可能会在后台检查 manifest 文件有未有改换(byte by byte)。发掘有涂改,就能够重新获得manifest 文件,对 Section:CACHE MANIFEST 下文件列表检查更新。manifest 文件与缓存文件的检讨更新也遵守浏览器缓存机制。

如用用户手动清了 AppCache 缓存,下一次加载时,浏览器会重新生成缓存,也可到头来1种缓存的换代。其它, Web App 也可用代码落成缓存更新。

剖判:AppCache 看起来是一种相比较好的缓存方法,除了缓存静态财富文件外,也符合构建 Web 离线 App。在其实使用中大略须求专注的地点,有一对能够说是”坑“。

  1. 要更新缓存的文件,需求更新包括它的 manifest 文件,那怕只加3个空格。常用的办法,是修改 manifest 文件注释中的版本号。如:# 2012-02-21 v1.0.0
  2. 被缓存的公文,浏览器是先选用,再经过检查 manifest 文件是不是有更新来更新缓存文件。这样缓存文件恐怕用的不是流行的本子。
  3. 在更新缓存进度中,假如有贰个文书更新退步,则全部更新会战败。
  4. manifest 和引用它的HTML要在平等 HOST。
  5. manifest 文件中的文件列表,假使是相对路线,则是相持 manifest 文件的相对路径。
  6. manifest 也可能有极大希望更新出错,导致缓存文件更新退步。
  7. 从不缓存的能源在早就缓存的 HTML 中不能够加载,就算有互联网。举个例子:
  8. manifest 文件自身不可能被缓存,且 manifest 文件的换代使用的是浏览器缓存机制。所以 manifest 文件的 Cache-Control 缓存时间不可能安装太长。

其余,依照官方文档,AppCache 已经不引入应用了,典型也不会再支撑。将来主流的浏览器都以还帮忙AppCache的,将来就不太鲜明了。

在Android 内嵌 Webview中,必要经过 Webview 设置接口启用 AppCache,同期还要设置缓存文件的贮存路线,别的还是能够设置缓存的长台湾空中大学小。

XHTML

WebView myWebView = (WebView) findViewById(R.id.webview); WebSettings webSettings = myWebView.getSettings(); webSettings.setAppCacheEnabled(true); final String cachePath = getApplicationContext().getDir("cache", Context.MODE_PRIVATE).getPath(); webSettings.setAppCachePath(cachePath); webSettings.setAppCacheMaxSize(5*1024*1024);

1
2
3
4
5
6
WebView myWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setAppCacheEnabled(true);
final String cachePath = getApplicationContext().getDir("cache", Context.MODE_PRIVATE).getPath();
webSettings.setAppCachePath(cachePath);
webSettings.setAppCacheMaxSize(5*1024*1024);

从数据库中剔除数据

去除数据利用delete措施,同上看似:

var request = db.transaction(['movies'], 'readwrite') .objectStore('movies') .delete('27054612'); // 通过键id来删除 request.onsuccess = function(event) { console.log('删除成功!'); console.log(event.target.result); };

1
2
3
4
5
6
7
8
var request =
    db.transaction(['movies'], 'readwrite')
      .objectStore('movies')
      .delete('27054612');  // 通过键id来删除
request.onsuccess = function(event) {
    console.log('删除成功!');
    console.log(event.target.result);
};

 

示例

在那个例子中,我们用三个音乐特辑应用作为示范。然而笔者并不筹划在那边从头到尾体现整个应用,而是把关系IndexedDB的部分挑出来解释。尽管大家对这些Web应用感兴趣的话,文章的末尾也提供了源代码的下载。首先,让我们来打开数据库并创设store:

JavaScript

// check if the indexedDB is supported if (!window.indexedDB) { throw 'IndexedDB is not supported!'; // of course replace that with some user-friendly notification } // variable which will hold the database connection var db; // open the database // first argument is database's name, second is it's version (I will talk about versions in a while) var request = indexedDB.open('album', 1); request.onerror = function (e) { console.log(e); }; // this will fire when the version of the database changes request.onupgradeneeded = function (e) { // e.target.result holds the connection to database db = e.target.result; // create a store to hold the data // first argument is the store's name, second is for options // here we specify the field that will serve as the key and also enable the automatic generation of keys with autoIncrement var objectStore = db.createObjectStore('cds', { keyPath: 'id', autoIncrement: true }); // create an index to search cds by title // first argument is the index's name, second is the field in the value // in the last argument we specify other options, here we only state that the index is unique, because there can be only one album with specific title objectStore.createIndex('title', 'title', { unique: true }); // create an index to search cds by band // this one is not unique, since one band can have several albums objectStore.createIndex('band', 'band', { unique: false }); };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// check if the indexedDB is supported
if (!window.indexedDB) {
    throw 'IndexedDB is not supported!'; // of course replace that with some user-friendly notification
}
 
// variable which will hold the database connection
var db;
 
// open the database
// first argument is database's name, second is it's version (I will talk about versions in a while)
var request = indexedDB.open('album', 1);
 
request.onerror = function (e) {
    console.log(e);
};
 
// this will fire when the version of the database changes
request.onupgradeneeded = function (e) {
    // e.target.result holds the connection to database
    db = e.target.result;
 
    // create a store to hold the data
    // first argument is the store's name, second is for options
    // here we specify the field that will serve as the key and also enable the automatic generation of keys with autoIncrement
    var objectStore = db.createObjectStore('cds', { keyPath: 'id', autoIncrement: true });
 
    // create an index to search cds by title
    // first argument is the index's name, second is the field in the value
    // in the last argument we specify other options, here we only state that the index is unique, because there can be only one album with specific title
    objectStore.createIndex('title', 'title', { unique: true });
 
    // create an index to search cds by band
    // this one is not unique, since one band can have several albums
    objectStore.createIndex('band', 'band', { unique: false });
};

深信上边的代码依然相当通俗易懂的。估算你也留意到上述代码中开辟数据库时会传入2个本子号,还用到了onupgradeneeded事件。当你以较新的版本张开数据库时就能够触发这些事件。纵然相应版本的数据库尚不存在,则会接触事件,随后我们就能够成立所需的store。接下来大家还创建了七个目录,1个用来标题寻觅,多个用来乐队寻觅。未来让大家再来看看怎么着增删专辑:

JavaScript

// adding $('#add-album').on('click', function () { // create the transaction // first argument is a list of stores that will be used, second specifies the flag // since we want to add something we need write access, so we use readwrite flag var transaction = db.transaction([ 'cds' ], 'readwrite'); transaction.onerror = function (e) { console.log(e); }; var value = { ... }; // read from DOM // add the album to the store var request = transaction.objectStore('cds').add(value); request.onsuccess = function (e) { // add the album to the UI, e.target.result is a key of the item that was added }; }); // removing $('.remove-album').on('click', function () { var transaction = db.transaction([ 'cds' ], 'readwrite'); var request = transaction.objectStore('cds').delete(/* some id got from DOM, converted to integer */); request.onsuccess = function () { // remove the album from UI } });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// adding
$('#add-album').on('click', function () {
    // create the transaction
    // first argument is a list of stores that will be used, second specifies the flag
    // since we want to add something we need write access, so we use readwrite flag
    var transaction = db.transaction([ 'cds' ], 'readwrite');
    transaction.onerror = function (e) {
        console.log(e);
    };
    var value = { ... }; // read from DOM
    // add the album to the store
    var request = transaction.objectStore('cds').add(value);
    request.onsuccess = function (e) {
        // add the album to the UI, e.target.result is a key of the item that was added
    };
});
 
// removing
$('.remove-album').on('click', function () {
    var transaction = db.transaction([ 'cds' ], 'readwrite');
    var request = transaction.objectStore('cds').delete(/* some id got from DOM, converted to integer */);
    request.onsuccess = function () {
        // remove the album from UI
    }
});

是或不是看起来直接明了?这里对数据库全体的操作都基于事务的,唯有如此才具保障数据的壹致性。今后最后要做的正是展现音乐专辑:

JavaScript

request.onsuccess = function (e) { if (!db) db = e.target.result; var transaction = db.transaction([ 'cds' ]); // no flag since we are only reading var store = transaction.objectStore('cds'); // open a cursor, which will get all the items from database store.openCursor().onsuccess = function (e) { var cursor = e.target.result; if (cursor) { var value = cursor.value; $('#albums-list tbody').append(' ' value.title '' value.band '' value.genre '' value.year '

1
2
3
4
5
6
7
8
9
10
11
12
request.onsuccess = function (e) {
    if (!db) db = e.target.result;
 
    var transaction = db.transaction([ 'cds' ]); // no flag since we are only reading
    var store = transaction.objectStore('cds');
    // open a cursor, which will get all the items from database
    store.openCursor().onsuccess = function (e) {
        var cursor = e.target.result;
        if (cursor) {
            var value = cursor.value;
            $('#albums-list tbody').append('
' value.title '' value.band '' value.genre '' value.year '

‘); // move to the next item in the cursor cursor.continue(); } }; }

那也不是13分复杂。可以望见,通过应用IndexedDB,可以很轻松的保存复杂对象,也足以透过索引来搜寻想要的内容:

JavaScript

function getAlbumByBand(band) { var transaction = db.transaction([ 'cds' ]); var store = transaction.objectStore('cds'); var index = store.index('band'); // open a cursor to get only albums with specified band // notice the argument passed to openCursor() index.openCursor(IDBKeyRange.only(band)).onsuccess = function (e) { var cursor = e.target.result; if (cursor) { // render the album // move to the next item in the cursor cursor.continue(); } }); }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function getAlbumByBand(band) {
    var transaction = db.transaction([ 'cds' ]);
    var store = transaction.objectStore('cds');
    var index = store.index('band');
    // open a cursor to get only albums with specified band
    // notice the argument passed to openCursor()
    index.openCursor(IDBKeyRange.only(band)).onsuccess = function (e) {
        var cursor = e.target.result;
        if (cursor) {
            // render the album
            // move to the next item in the cursor
            cursor.continue();
        }
    });
}

行使索引的时候和行使store一致,也能经过游标(cursor)来遍历。由于同1个索引值名下或许有几许条数据(假设索引不是unique的话),所以那边大家须求采纳IDBKeyRange。它能依靠钦命的函数对结果集进行过滤。这里,我们只想依照钦定的乐队举办搜寻,所以大家用到了only()函数。也能采纳别的类似于lowerBound()upperBound()bound()等函数,它们的魔法也是不言自明的。

2.5 Indexed Database

IndexedDB 也是一种数据库的积攒机制,但分化于已经不复接济的 Web SQL Database。IndexedDB 不是价值观的关周到据库,可归为 NoSQL 数据库。IndexedDB 又象是于 Dom Storage 的 key-value 的存款和储蓄格局,但效益越来越强有力,且存款和储蓄空间更加大。

IndexedDB 存款和储蓄数据是 key-value 的样式。Key 是须求,且要唯1;Key 能够友善定义,也可由系统自动生成。Value 也是少不了的,但 Value 特别灵活,能够是其他项目标对象。一般 Value 都以由此 Key 来存取的。

IndexedDB 提供了一组 API,能够实行数据存、取以及遍历。这一个 API 都以异步的,操作的结果都以在回调中回到。

上面代码演示了 IndexedDB 中 DB 的开辟(创造)、存款和储蓄对象(可见道成有关周密据的”表“)的创设及数量存取、遍历基本成效。

XHTML

<script type="text/javascript"> var db; window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; //浏览器是或不是辅助IndexedDB if (window.indexedDB) { //展开数据库,若是未有,则开创 var openRequest = window.indexedDB.open("people_db", 壹); //DB版本设置或升官时回调 openRequest.onupgradeneeded = function(e) { console.log("Upgrading..."); var thisDB = e.target.result; if(!thisDB.objectStoreNames.contains("people")) { console.log("Create Object Store: people."); //创造存款和储蓄对象,类似于关周详据库的表 thisDB.createObjectStore("people", { autoIncrement:true }); //创设存款和储蓄对象, 还创建索引 //var objectStore = thisDB.createObjectStore("people",{ autoIncrement:true }); // //first arg is name of index, second is the path (col); //objectStore.createIndex("name","name", {unique:false}); //objectStore.createIndex("email","email", {unique:true}); } } //DB成功开荒回调 openRequest.onsuccess = function(e) { console.log("Success!"); //保存全局的数据库对象,前面会用到 db = e.target.result; //绑定开关点击事件 document.querySelector("#addButton").addEventListener("click", addPerson, false); document.querySelector("#getButton").addEventListener("click", getPerson, false); document.querySelector("#getAllButton").addEventListener("click", getPeople, false); document.querySelector("#getByName").add伊夫ntListener("click", getPeopleByNameIndex一, false); } //DB打开失利回调 openRequest.onerror = function(e) { console.log("Error"); console.dir(e); } }else{ alert('Sorry! Your browser doesn't support the IndexedDB.'); } //增加一条记下 function addPerson(e) { var name = document.querySelector("#name").value; var email = document.querySelector("#email").value; console.log("About to add " name "/" email); var transaction = db.transaction(["people"],"readwrite"); var store = transaction.objectStore("people"); //Define a person var person = { name:name, email:email, created:new Date() } //Perform the add var request = store.add(person); //var request = store.put(person, 2); request.onerror = function(e) { console.log("Error",e.target.error.name); //some type of error handler } request.onsuccess = function(e) { console.log("Woot! Did it."); } } //通过KEY查询记录 function getPerson(e) { var key = document.querySelector("#key").value; if(key === "" || isNaN(key)) return; var transaction = db.transaction(["people"],"readonly"); var store = transaction.objectStore("people"); var request = store.get(Number(key)); request.onsuccess = function(e) { var result = e.target.result; console.dir(result); if(result) { var s = "<p><h2>Key " key "</h2></p>"; for(var field in result) { s = field "=" result[field] "<br/>"; } document.querySelector("#status").innerHTML = s; } else { document.querySelector("#status").innerHTML = "<h2>No match!</h二>"; } } } //获取具有记录 function getPeople(e) { var s = ""; db.transaction(["people"], "readonly").objectStore("people").openCursor().onsuccess = function(e) { var cursor = e.target.result; if(cursor) { s = "<p><h2>Key " cursor.key "</h2></p>"; for(var field in cursor.value) { s = field "=" cursor.value[field] "<br/>"; } s ="</p>"; cursor.continue(); } document.querySelector("#status二").innerHTML = s; } } //通过索引查询记录 function getPeopleByNameIndex(e) { var name = document.querySelector("#name1").value; var transaction = db.transaction(["people"],"readonly"); var store = transaction.objectStore("people"); var index = store.index("name"); //name is some value var request = index.get(name); request.onsuccess = function(e) { var result = e.target.result; if(result) { var s = "<p><h2>Name " name "</h2><p>"; for(var field in result) { s = field "=" result[field] "<br/>"; } s ="</p>"; } else { document.querySelector("#status3").innerHTML = "<h2>No match!</h二>"; } } } //通过索引查询记录 function getPeopleByNameIndex一(e) { var s = ""; var name = document.querySelector("#name1").value; var transaction = db.transaction(["people"],"readonly"); var store = transaction.objectStore("people"); var index = store.index("name"); //name is some value index.openCursor().onsuccess = function(e) { var cursor = e.target.result; if(cursor) { s = "<p><h2>Key " cursor.key "</h2></p>"; for(var field in cursor.value) { s = field "=" cursor.value[field] "<br/>"; } s ="</p>"; cursor.continue(); } document.querySelector("#status三").innerHTML = s; } } </script> <p>增加数量<br/> <input type="text" id="name" placeholder="Name"><br/> <input type="email" id="email" placeholder="Email"><br/> <button id="addButton">Add Data</button> </p> <p>依据Key查询数据<br/> <input type="text" id="key" placeholder="Key"><br/> <button id="getButton">Get Data</button> </p> <div id="status" name="status"></div> <p>获取具有数据<br/> <button id="getAllButton">Get 伊夫ryOne</button> </p> <div id="status二" name="status二"></div> <p>依据目录:Name查询数据<br/> <input type="text" id="name1" placeholder="Name"><br/> <button id="getByName">Get ByName</button> </p> <div id="status三" name="status三"></div>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
<script type="text/javascript">
 
var db;
 
window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
 
//浏览器是否支持IndexedDB
if (window.indexedDB) {
   //打开数据库,如果没有,则创建
   var openRequest = window.indexedDB.open("people_db", 1);
 
   //DB版本设置或升级时回调
   openRequest.onupgradeneeded = function(e) {
       console.log("Upgrading...");
 
       var thisDB = e.target.result;
       if(!thisDB.objectStoreNames.contains("people")) {
           console.log("Create Object Store: people.");
 
           //创建存储对象,类似于关系数据库的表
           thisDB.createObjectStore("people", { autoIncrement:true });
 
          //创建存储对象, 还创建索引
          //var objectStore = thisDB.createObjectStore("people",{ autoIncrement:true });
         // //first arg is name of index, second is the path (col);
        //objectStore.createIndex("name","name", {unique:false});
       //objectStore.createIndex("email","email", {unique:true});
     }
}
 
//DB成功打开回调
openRequest.onsuccess = function(e) {
    console.log("Success!");
 
    //保存全局的数据库对象,后面会用到
    db = e.target.result;
 
   //绑定按钮点击事件
     document.querySelector("#addButton").addEventListener("click", addPerson, false);
 
    document.querySelector("#getButton").addEventListener("click", getPerson, false);
 
    document.querySelector("#getAllButton").addEventListener("click", getPeople, false);
 
    document.querySelector("#getByName").addEventListener("click", getPeopleByNameIndex1, false);
}
 
  //DB打开失败回调
  openRequest.onerror = function(e) {
      console.log("Error");
      console.dir(e);
   }
 
}else{
    alert('Sorry! Your browser doesn't support the IndexedDB.');
}
 
//添加一条记录
function addPerson(e) {
    var name = document.querySelector("#name").value;
    var email = document.querySelector("#email").value;
 
    console.log("About to add " name "/" email);
 
    var transaction = db.transaction(["people"],"readwrite");
var store = transaction.objectStore("people");
 
   //Define a person
   var person = {
       name:name,
       email:email,
       created:new Date()
   }
 
   //Perform the add
   var request = store.add(person);
   //var request = store.put(person, 2);
 
   request.onerror = function(e) {
       console.log("Error",e.target.error.name);
       //some type of error handler
   }
 
   request.onsuccess = function(e) {
      console.log("Woot! Did it.");
   }
}
 
//通过KEY查询记录
function getPerson(e) {
    var key = document.querySelector("#key").value;
    if(key === "" || isNaN(key)) return;
 
    var transaction = db.transaction(["people"],"readonly");
    var store = transaction.objectStore("people");
 
    var request = store.get(Number(key));
 
    request.onsuccess = function(e) {
        var result = e.target.result;
        console.dir(result);
        if(result) {
           var s = "<p><h2>Key " key "</h2></p>";
           for(var field in result) {
               s = field "=" result[field] "<br/>";
           }
           document.querySelector("#status").innerHTML = s;
         } else {
            document.querySelector("#status").innerHTML = "<h2>No match!</h2>";
         }
     }
}
 
//获取所有记录
function getPeople(e) {
 
    var s = "";
 
     db.transaction(["people"], "readonly").objectStore("people").openCursor().onsuccess = function(e) {
        var cursor = e.target.result;
        if(cursor) {
            s = "<p><h2>Key " cursor.key "</h2></p>";
            for(var field in cursor.value) {
                s = field "=" cursor.value[field] "<br/>";
            }
            s ="</p>";
            cursor.continue();
         }
         document.querySelector("#status2").innerHTML = s;
     }
}
 
//通过索引查询记录
function getPeopleByNameIndex(e)
{
    var name = document.querySelector("#name1").value;
 
    var transaction = db.transaction(["people"],"readonly");
    var store = transaction.objectStore("people");
    var index = store.index("name");
 
    //name is some value
    var request = index.get(name);
 
    request.onsuccess = function(e) {
       var result = e.target.result;
       if(result) {
           var s = "<p><h2>Name " name "</h2><p>";
           for(var field in result) {
               s = field "=" result[field] "<br/>";
           }
           s ="</p>";
    } else {
        document.querySelector("#status3").innerHTML = "<h2>No match!</h2>";
     }
   }
}
 
//通过索引查询记录
function getPeopleByNameIndex1(e)
{
    var s = "";
 
    var name = document.querySelector("#name1").value;
 
    var transaction = db.transaction(["people"],"readonly");
    var store = transaction.objectStore("people");
    var index = store.index("name");
 
    //name is some value
    index.openCursor().onsuccess = function(e) {
        var cursor = e.target.result;
        if(cursor) {
            s = "<p><h2>Key " cursor.key "</h2></p>";
            for(var field in cursor.value) {
                s = field "=" cursor.value[field] "<br/>";
            }
            s ="</p>";
            cursor.continue();
         }
         document.querySelector("#status3").innerHTML = s;
     }
}
 
</script>
 
<p>添加数据<br/>
<input type="text" id="name" placeholder="Name"><br/>
<input type="email" id="email" placeholder="Email"><br/>
<button id="addButton">Add Data</button>
</p>
 
<p>根据Key查询数据<br/>
<input type="text" id="key" placeholder="Key"><br/>
<button id="getButton">Get Data</button>
</p>
<div id="status" name="status"></div>
 
<p>获取所有数据<br/>
<button id="getAllButton">Get EveryOne</button>
</p>
<div id="status2" name="status2"></div>
 
<p>根据索引:Name查询数据<br/>
    <input type="text" id="name1" placeholder="Name"><br/>
    <button id="getByName">Get ByName</button>
</p>
<div id="status3" name="status3"></div>

将上边包车型大巴代码复制到 indexed_db.html 中,用 谷歌 Chrome 浏览器展开,就足以加多、查询数据。在 Chrome 的开采者工具中,能查看创造的 DB 、存款和储蓄对象(可明白成表)以及表中增加的数额。

澳门新浦京娱乐场网站 17

IndexedDB 有个要命壮大的法力,正是 index(索引)。它可对 Value 对象中其余属性生成索引,然后能够依附索引实行 Value 对象的高效查询。

要生成索引或支撑索引查询数据,必要在首次生成存款和储蓄对象时,调用接口生成属性的目录。能够同有的时候候对指标的三个不一致属性成立索引。如下面代码就对name 和 email 三个属性都生成了目录。

XHTML

var objectStore = thisDB.createObjectStore("people",{ autoIncrement:true }); //first arg is name of index, second is the path (col); objectStore.createIndex("name","name", {unique:false}); objectStore.createIndex("email","email", {unique:true});

1
2
3
4
var objectStore = thisDB.createObjectStore("people",{ autoIncrement:true });
//first arg is name of index, second is the path (col);
objectStore.createIndex("name","name", {unique:false});
objectStore.createIndex("email","email", {unique:true});

生成索引后,就能够依照索引进行数量的询问。

主导使用,加载品质优化。XHTML

function getPeopleByNameIndex(e) { var name = document.querySelector("#name1").value; var transaction = db.transaction(["people"],"readonly"); var store = transaction.objectStore("people"); var index = store.index("name"); //name is some value var request = index.get(name); request.onsuccess = function(e) { var result = e.target.result; if(result) { var s = "<p><h2>Name " name "</h2><p>"; for(var field in result) { s = field "=" result[field] "<br/>"; } s ="</p>"; } else { document.querySelector("#status3").innerHTML = "<h2>No match!</h2>"; } } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function getPeopleByNameIndex(e)
{
var name = document.querySelector("#name1").value;
 
var transaction = db.transaction(["people"],"readonly");
var store = transaction.objectStore("people");
var index = store.index("name");
 
//name is some value
var request = index.get(name);
request.onsuccess = function(e) {
    var result = e.target.result;
    if(result) {
        var s = "<p><h2>Name " name "</h2><p>";
        for(var field in result) {
            s = field "=" result[field] "<br/>";
        }
        s ="</p>";
    } else {
        document.querySelector("#status3").innerHTML = "<h2>No match!</h2>";
    }
  }
}

分析:IndexedDB 是一种灵活且效率庞大的数据存款和储蓄机制,它集结了 Dom Storage 和 Web SQL Database 的优点,用于存款和储蓄大块或复杂结构的数目,提供越来越大的贮存空间,使用起来也相比轻松。能够看做 Web SQL Database 的代替。不太符合静态文件的缓存。

  1. 以key-value 的方式存取对象,能够是其余类型值或对象,包罗二进制。
  2. 能够对指标任何属性生成索引,方便查询。
  3. 很大的蕴藏空间,暗许推荐250MB(分 HOST),比 Dom Storage 的5MB 要大的多。
  4. 经过数据库的事情(tranction)机制进行数量操作,保险数据1致性。
  5. 异步的 API 调用,制止形成等待而影响体验。

Android 在4.4上马参预对 IndexedDB 的帮助,只需展开允许 JS 施行的按键就好了。

XHTML

WebView myWebView = (WebView) findViewById(R.id.webview); WebSettings webSettings = myWebView.getSettings(); webSettings.setJavaScriptEnabled(true);

1
2
3
WebView myWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);

从数额中获取数据

获取数据使用get艺术,同上好像:

var request = db.transaction('movies') .objectStore('movies') .get('99996八贰'); // 通过键alt来获得 request.onsuccess = function(event) { console.log('获取成功!', event.target.result); };

1
2
3
4
5
6
7
var request =
    db.transaction('movies')
       .objectStore('movies')
       .get('9999682');  // 通过键alt来获取
request.onsuccess = function(event) {
    console.log('获取成功!', event.target.result);
};

总结

能够瞥见,在Web应用中运用离线数据并不是13分复杂。希望通过翻阅这篇作品,各位能够在Web应用中进入离线数据的法力,使得你们的接纳越来越温馨易用。你能够在这里下载全体的源码,尝试一下,恐怕涂改,或许用在你们的施用中。

赞 收藏 评论

2.6 File System API

File System API 是 H5 新加盟的存款和储蓄机制。它为 Web App 提供了1个虚构的文件系统,仿佛 Native App 访问当麻芋果件系统同样。由于安全性的考虑,这么些虚拟文件系统有明确的限定。Web App 在编造的文件系统中,能够开展文件(夹)的开创、读、写、删除、遍历等操作。

File System API 也是一种可选的缓存机制,和后面包车型地铁 SQLDatabase、IndexedDB 和 AppCache 等同样。File System API 有投机的片段特定的优势:

  1. 能够满足大块的二进制数据( large binary blobs)存储要求。
  2. 能够透过预加载能源文件来抓实质量。
  3. 能够直接编辑文件。

浏览器给虚拟文件系统提供了二种档案的次序的囤积空间:临时的和长久性的。不常的仓库储存空间是由浏览器自动分配的,但恐怕被浏览器回收;长久性的存款和储蓄空间必要突显的提请,申请时浏览器会给用户1提醒,必要用户展开确认。长久性的积累空间是 WebApp 本人管理,浏览器不会回收,也不会免去内容。持久性的储存空间大小是透过分配的定额来保管的,第3回申请时会二个最先的配额,分配的定额用完需求重新申请。

编造的文件系统是运作在沙盒中。不相同 WebApp 的虚拟文件系统是并行隔开分离的,虚拟文件系统与当三步跳件系统也是互相隔开分离的。

File System API 提供了一组文件与公事夹的操作接口,有伙同和异步多少个版本,可知足差别的应用境况。下面通过三个文件创造、读、写的例子,演示下轻松的成效与用法。

主导使用,加载品质优化。XHTML

<script type="text/javascript"> window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem; //请求不经常文件的囤积空间 if (window.requestFileSystem) { window.requestFileSystem(window.TEMPORA福特ExplorerY, 伍*1024*1024, initFS, errorHandler); }else{ alert('Sorry! Your browser doesn't support the FileSystem API'); } //请求成功回调 function initFS(fs){ //在根目录下开垦log.txt文件,假设不设有就成立//fs正是打响再次来到的文件系统对象,fs.root代表根目录 fs.root.getFile('log.txt', {create: true}, function(fileEntry) { //fileEntry是回到的三个文书对象,代表张开的文件 //向文件写入钦定内容 writeFile(fileEntry); //将写入的内容又读出来,显示在页面上 readFile(fileEntry); }, errorHandler); } //读取文件内容 function readFile(fileEntry) { console.log('readFile'); // Get a File object representing the file, // then use FileReader to read its contents. fileEntry.file(function(file) { console.log('createReader'); var reader = new FileReader(); reader.onloadend = function(e) { console.log('onloadend'); var txtArea = document.createElement('textarea'); txtArea.value = this.result; document.body.appendChild(txtArea); }; reader.readAsText(file); }, errorHandler); } //向文件写入钦命内容 function writeFile(fileEntry) { console.log('writeFile'); // Create a FileWriter object for our FileEntry (log.txt). fileEntry.createWriter(function(fileWriter) { console.log('createWriter'); fileWriter.onwriteend = function(e) { console.log('Write completed'); }; fileWriter.onerror = function(e) { console.log('Write failed: ' e.toString()); }; // Create a new Blob and write it to log.txt. var blob = new Blob(['Hello, World!'], {type: 'text/plain'}); fileWriter.write(blob); }, errorHandler); } function errorHandler(err){ var msg = 'An error occured: ' err; console.log(msg); }; </script>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
<script type="text/javascript">
 
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
 
//请求临时文件的存储空间
if (window.requestFileSystem) {
     window.requestFileSystem(window.TEMPORARY, 5*1024*1024, initFS, errorHandler);
}else{
  alert('Sorry! Your browser doesn't support the FileSystem API');
}
 
//请求成功回调
function initFS(fs){
 
  //在根目录下打开log.txt文件,如果不存在就创建
  //fs就是成功返回的文件系统对象,fs.root代表根目录
  fs.root.getFile('log.txt', {create: true}, function(fileEntry) {
 
  //fileEntry是返回的一个文件对象,代表打开的文件
 
  //向文件写入指定内容
  writeFile(fileEntry);
 
  //将写入的内容又读出来,显示在页面上
  readFile(fileEntry);
 
  }, errorHandler);
}
 
//读取文件内容
function readFile(fileEntry)
{
    console.log('readFile');
 
   // Get a File object representing the file,
   // then use FileReader to read its contents.
   fileEntry.file(function(file) {
 
     console.log('createReader');
 
      var reader = new FileReader();
 
      reader.onloadend = function(e) {
 
        console.log('onloadend');
 
        var txtArea = document.createElement('textarea');
        txtArea.value = this.result;
        document.body.appendChild(txtArea);
      };
 
      reader.readAsText(file);
   }, errorHandler);
}
 
//向文件写入指定内容
function writeFile(fileEntry)
{
    console.log('writeFile');
 
    // Create a FileWriter object for our FileEntry (log.txt).
    fileEntry.createWriter(function(fileWriter) {
 
      console.log('createWriter');
 
      fileWriter.onwriteend = function(e) {
        console.log('Write completed');
      };
 
        fileWriter.onerror = function(e) {
          console.log('Write failed: ' e.toString());
        };
 
        // Create a new Blob and write it to log.txt.
        var blob = new Blob(['Hello, World!'], {type: 'text/plain'});
 
        fileWriter.write(blob);
 
     }, errorHandler);
}
 
function errorHandler(err){
var msg = 'An error occured: ' err;
console.log(msg);
};
 
</script>

将上边代码复制到 file_system_api.html 文件中,用 谷歌 Chrome 浏览器伸开(以后 File System API 唯有 Chrome 四三 、Opera 32 以及 Chrome for Android 4陆 那八个浏览器援救)。由于 谷歌 Chrome 禁止使用了地点 HTML 文件中的 File System API功用,在运转 Chrome 时,要增多”—allow-file-access-from-files“命令行参数。

澳门新浦京娱乐场网站 18

地方截图,左边是 HTML 运转的结果,右侧是 Chrome 开荒者工具中看出的 Web 的文件系统。基本上 H5的三种缓存机制的数额都能在这一个开垦者工具看到,极其便宜。

剖析:File System API 给 Web App 带来了文件系统的效用,Native 文件系统的功能在 Web App 中都有打点的贯彻。任何索要经过文件来治本数据,或通过文件系统进行数量管理的景色都相比吻合。

到当下,Android 系统的 Webview 还不援助 File System API。


5、使用索引

在日前,大家创制了八个目录alttitle, 配置对象里面包车型地铁unique性格标记该值是不是唯一

近日我们想找到alt属性值为https://movie.douban.com/subject/26639033/的靶子,就足以应用索引。

var alt = ''; var objectStore = db.transaction('movies').objectStore('movies'); // 张开对象存款和储蓄空间 var index = objectStore.index('alt'); // 使用索引'alt' var request = index.get(alt); // 创设一个搜索数据的伸手 request.onsuccess = function(event) { console.log('The result is:', event.target.result); }; var noDataTest = index.get('testalt'); // 未有该对象时的测试 noDataTest.onsuccess = function(event) { console.log('success! result:', event.target.result); }; noDataTest.onerror = function(event) { console.log('error! event:', event); };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var alt = 'https://movie.douban.com/subject/26639033/';
var objectStore = db.transaction('movies').objectStore('movies');  // 打开对象存储空间
var index = objectStore.index('alt');  // 使用索引'alt'
var request = index.get(alt);          // 创建一个查找数据的请求
request.onsuccess = function(event) {
    console.log('The result is:', event.target.result);
};
var noDataTest = index.get('testalt');  // 没有该对象时的测试
noDataTest.onsuccess = function(event) {
    console.log('success! result:', event.target.result);
};
noDataTest.onerror = function(event) {
    console.log('error! event:', event);
};

澳门新浦京娱乐场网站 19

动用唯一性索引,大家得以拿走唯一的一条数据(恐怕undefined),那么使用非唯1性索引呢?
大家向数据库中插入一条数据,使title重复:

db.transaction('movies', 'readwrite').objectStore('movies') .add({ alt: '', title: '寻梦环游记', year: '2017', id: '12345678玖' }) .onsuccess = function(event) { console.log('插入成功!'); };

1
2
3
4
5
6
7
db.transaction('movies', 'readwrite').objectStore('movies')
.add({ alt: 'https://movie.douban.com/subject/27054612121/',
    title: '寻梦环游记',
    year: '2017',
    id: '123456789'
})
.onsuccess = function(event) { console.log('插入成功!'); };

采用索引title获取title值为寻梦环游记的对象:

var indexName = 'title', title = '寻梦环游记'; var objectStore = db.transaction('movies').objectStore('movies'); var index = objectStore.index(indexName); // 使用索引'alt' var request = index.get(title); // 创造三个搜索数据的乞请 request.onsuccess = function(event) { console.log('The result is:', event.target.result); };

1
2
3
4
5
6
7
var indexName = 'title', title = '寻梦环游记';
var objectStore = db.transaction('movies').objectStore('movies');
var index = objectStore.index(indexName);  // 使用索引'alt'
var request = index.get(title);          // 创建一个查找数据的请求
request.onsuccess = function(event) {
    console.log('The result is:', event.target.result);
};

澳门新浦京娱乐场网站 20

笔者们取得的是键值微小的特别对象.

利用一回索引,大家不得不获取一条数据; 就算大家必要获得全数title属性值为寻梦环游记的指标,我们能够使用游标.

关于笔者:njuyz

澳门新浦京娱乐场网站 21

(天涯论坛今日头条:@njuyz) 个人主页 · 笔者的稿子 · 11

澳门新浦京娱乐场网站 22

三 移动端 Web 加载质量(缓存)优化

解析完 H5提供的各类缓存机制,回到移动端(针对 Android,也许也适用于 iOS)的场景。未来 Android App(包涵手 Q 和 WX)许多嵌入了 Webview 的组件(系统 Webview 或 QQ 游览器的 X五组件),通过内嵌Webview 来加载一些H5的运行活动页面或新闻页。那样可充足发挥Web前端的优势:飞速支付、发表,灵活上下线。但 Webview 也许有部分不行忽略的难点,比较优异的就是加载相对极慢,会相对消耗较多流量。

由此对部分 H伍页面实行调弄整理及抓包开掘,每趟加载贰个H5页面,都会有较多的哀求。除了 HTML 主 U昂科威L 本人的呼吁外,HTML外部引用的 JS、CSS、字体文件、图片都以叁个独门的 HTTP 请求,每3个呼吁都串行的(也可以有一而再复用)。这么多请求串起来,再增添浏览器分析、渲染的年华,Web 全体的加载时间变得较长;请求文件更加的多,消耗的流量也会越来越多。大家可综合使用方面提起两种缓存机制,来增加援助大家优化 Web 的加载品质。

澳门新浦京娱乐场网站 23

敲定:综合各个缓存机制比较,对于静态文件,如 JS、CSS、字体、图片等,适合通过浏览器缓存机制来举办缓存,通过缓存文件可大幅度提升Web 的加载速度,且节省流量。但也可以有1部分欠缺:缓存文件需求第二回加载后才会生出;浏览器缓存的仓储空间有限,缓存有被免去的恐怕;缓存的文件未有校验。要消除这几个不足,能够参照手 Q 的离线包,它使得的缓慢解决了那个不足。

对此 Web 在地头或服务器获取的数据,能够经过 Dom Storage 和 IndexedDB 实行缓存。也在早晚水准上压缩和 Server 的相互,升高加载速度,同临时候节约流量。

理所必然 Web 的性质优化,还包蕴精选妥善的图片大小,防止 JS 和 CSS 产生的不通等。这就供给 Web 前端的同事依据部分正经和一部分调理工具举行优化了。

腾讯Bugly特约小编:贺辉超

1 赞 9 收藏 评论

陆、使用游标

获得三个得以操作游标的央求对象有八个办法:

  • openCursor(keyRange, direction)
  • openKeyCursor(keyRange, direction)
    那多少个章程接收的参数同样, 多少个参数都是可选的: 首个参数是限量值得范围,第四个参数是钦定游标方向

游标的利用有以下几处:

  • 在对象存款和储蓄空间上接纳: var cursor = objectStore.openCursor()
  • 在目录对象上应用: var cursor = index.openCursor()

有关作者:腾讯bugly

澳门新浦京娱乐场网站 24

Bugly是腾讯里面产品质量监察和控制平台的外发版本,匡助iOS和Android两大主流平台,其根本职能是App公布之后,对用户侧发生的crash以及卡顿现象进行监督并反映,让开辟同学能够第偶然间精通到app的成色意况,及时修改。近来Tencent之中有着的制品,均在选拔其进行线上产品的咽气监察和控制。腾讯内部协会4年打... 个人主页 · 笔者的小说 · 3 ·  

澳门新浦京娱乐场网站 25

在对象存款和储蓄空间上应用游标

行使游标常见的1种方式是获得对象存款和储蓄空间上的全部数据.

var list = []; var objectStore = db.transaction('movies').objectStore('movies'); objectStore.openCursor().onsuccess = function(event) { var cursor = event.target.result; if (cursor) { console.log('cursor:', cursor); list.push(cursor.value); cursor.continue(); } else { console.log('Get all data:', list); } };

1
2
3
4
5
6
7
8
9
10
11
12
var list = [];
var objectStore = db.transaction('movies').objectStore('movies');
objectStore.openCursor().onsuccess = function(event) {
    var cursor = event.target.result;
    if (cursor) {
        console.log('cursor:', cursor);
        list.push(cursor.value);
        cursor.continue();
    } else {
        console.log('Get all data:', list);
    }
};

澳门新浦京娱乐场网站 26

使用游标时,供给在中标回调里得到result目的,剖断是还是不是取完了多少:若数据已取完,resultundefined; 若未取完,则result是个IDBCursorWithValue对象,需调用continue()方法继续取多少。 也得以依附自个儿需要, 对数码举办过滤。

indexedDB2专门的学业中,在对象存款和储蓄空间对象上纳入了贰个getAll()办法,能够拿走具备目的:

objectStore.getAll().onsuccess = function(event) { console.log('result:', event.target.result); };

1
2
3
objectStore.getAll().onsuccess = function(event) {
    console.log('result:', event.target.result);
};

在目录上利用游标

跟着本文上述使用索引的例证,在目录title上使用openCursor()主意时,若不传参数,则会遍历全数数据,在成功回调中的到的result指标有以下属性:

  • key 数据库中这条对象的title属性值
  • primaryKey 数据库中那条对象的alt
  • value 数据库中那条对象
  • direction openCursor()方法传入的第三个指标,默许值为next
  • source IDBIndex对象 比如如下:
var index = db .transaction('movies')
.objectStore('movies').index('title'); index.openCursor().onsuccess
= function(event) { var cursor = event.target.result; if (cursor) {
console.log('cursor:', cursor); cursor.continue(); } };

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f37afae763506229096-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f37afae763506229096-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f37afae763506229096-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f37afae763506229096-4">
4
</div>
<div class="crayon-num" data-line="crayon-5b8f37afae763506229096-5">
5
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f37afae763506229096-6">
6
</div>
<div class="crayon-num" data-line="crayon-5b8f37afae763506229096-7">
7
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f37afae763506229096-8">
8
</div>
<div class="crayon-num" data-line="crayon-5b8f37afae763506229096-9">
9
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f37afae763506229096-10">
10
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f37afae763506229096-1" class="crayon-line">
var index = db
</div>
<div id="crayon-5b8f37afae763506229096-2" class="crayon-line crayon-striped-line">
.transaction('movies')
</div>
<div id="crayon-5b8f37afae763506229096-3" class="crayon-line">
.objectStore('movies').index('title');
</div>
<div id="crayon-5b8f37afae763506229096-4" class="crayon-line crayon-striped-line">
index.openCursor().onsuccess = function(event) {
</div>
<div id="crayon-5b8f37afae763506229096-5" class="crayon-line">
  var cursor = event.target.result;
</div>
<div id="crayon-5b8f37afae763506229096-6" class="crayon-line crayon-striped-line">
  if (cursor) {
</div>
<div id="crayon-5b8f37afae763506229096-7" class="crayon-line">
      console.log('cursor:', cursor);
</div>
<div id="crayon-5b8f37afae763506229096-8" class="crayon-line crayon-striped-line">
      cursor.continue();
</div>
<div id="crayon-5b8f37afae763506229096-9" class="crayon-line">
  }
</div>
<div id="crayon-5b8f37afae763506229096-10" class="crayon-line crayon-striped-line">
};
</div>
</div></td>
</tr>
</tbody>
</table>


[![](http://www.bonzeragro.com/uploads/allimg/190608/0555511929-26.png)](http://www.bonzeragro.com/uploads/allimg/190608/0555511929-26.png)

在索引title上使用openKeyCursor()方式,若不传参数,一样也会遍历全部数据,result对象属性如下:

  • key 数据库中那条对象的title属性值
  • primaryKey 数据库中那条对象的alt
  • direction openCursor()方法传入的第一个对象,私下认可值为next
  • source altBIndex对象

openCursor()艺术比较,获得的数据少四个value属性,是从未艺术获得存款和储蓄对象的别的部分

眼下提及,大家要依据目录title获得具有title属性值为寻梦环游记的对象,要运用游标,而又不想遍历全体数据,那时就要采用openCursor()的首先个参数: keyRange

keyRange是限制游标遍历的数目范围,通过IDBKeyRange的局地格局设置该值:

var singleKeyRange = IDBKeyRange.only("寻梦环游记"), list = []; var index = db .transaction('movies') .objectStore('movies').index('title'); index.openCursor(singleKeyRange).onsuccess = function(event) { var cursor = event.target.result; if (cursor) { console.log('cursor.value:', cursor.value); list.push(cursor.value); cursor.continue(); } else { console.log('list:', list); } };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var singleKeyRange = IDBKeyRange.only("寻梦环游记"), list = [];
var index = db
.transaction('movies')
.objectStore('movies').index('title');
index.openCursor(singleKeyRange).onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
console.log('cursor.value:', cursor.value);
list.push(cursor.value);
cursor.continue();
} else {
    console.log('list:', list);
}
};

澳门新浦京娱乐场网站 27

IDBKeyRange其余一些措施:

// 匹配全体在 "Bill" 前边的, 包蕴 "Bill" var lowerBoundKeyRange = IDBKeyRange.lowerBound("Bill"); // 相称全部在 “Bill” 前边的, 不过没有要求包蕴 "Bill" var lowerBoundOpenKeyRange = IDBKeyRange.lowerBound("Bill", true); // 相称全部在'堂娜'前边的, 但是不蕴涵"堂娜" var upperBoundOpenKeyRange = IDBKeyRange.upperBound("堂娜", true); // 相称全数在"Bill" 和 "堂娜" 之间的, 可是不包含 "堂娜" var boundKeyRange = IDBKeyRange.bound("比尔", "堂娜", false, true);

1
2
3
4
5
6
7
8
9
10
11
// 匹配所有在 "Bill" 前面的, 包括 "Bill"
var lowerBoundKeyRange = IDBKeyRange.lowerBound("Bill");
 
// 匹配所有在 “Bill” 前面的, 但是不需要包括 "Bill"
var lowerBoundOpenKeyRange = IDBKeyRange.lowerBound("Bill", true);
 
// 匹配所有在'Donna'后面的, 但是不包括"Donna"
var upperBoundOpenKeyRange = IDBKeyRange.upperBound("Donna", true);
 
// 匹配所有在"Bill" 和 "Donna" 之间的, 但是不包括 "Donna"
var boundKeyRange = IDBKeyRange.bound("Bill", "Donna", false, true);

越来越多请参照他事他说加以考察 MDN|IDBKeyRange

游标私下认可遍历方向是按主键从小到大,不时候大家倒序遍历,此时能够给openCursor()主意传递第二个参数: direction: next|nextunique|prev|prevunique

var singleKeyRange = IDBKeyRange.only("寻梦环游记"), list = []; var index = db .transaction('movies') .objectStore('movies').index('title'); index.openCursor(singleKeyRange, 'prev').onsuccess = function(event) { var cursor = event.target.result; if (cursor) { console.log('cursor.value:', cursor.value); list.push(cursor.value); cursor.continue(); } else { console.log('list:', list); } };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var singleKeyRange = IDBKeyRange.only("寻梦环游记"), list = [];
var index = db
.transaction('movies')
.objectStore('movies').index('title');
index.openCursor(singleKeyRange, 'prev').onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
console.log('cursor.value:', cursor.value);
list.push(cursor.value);
cursor.continue();
} else {
    console.log('list:', list);
}
};

传了prev的结果是按倒序遍历的.

因为 “name” 索引不是唯一的,那就有望存在具有同样 name 的多条记下。 要注意的是这种意况不容许发生在目的存款和储蓄空间上,因为键必须永久是独步天下的。 假如你想要在游标在目录迭代进度中过滤出双重的,你能够传递 nextunique(或prevunique, 倘让你正在向后查找)作为方向参数。 当 nextunique 或是 prevunique 被使用时,被再次来到的要命总是键最小的笔录。

var singleKeyRange = IDBKeyRange.only("寻梦环游记"), list = []; var index = db .transaction('movies') .objectStore('movies').index('title'); index.openCursor(singleKeyRange, 'prevunique').onsuccess = function(event) { var cursor = event.target.result; if (cursor) { console.log('cursor.value:', cursor.value); list.push(cursor.value); cursor.continue(); } else { console.log('list:', list); } };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var singleKeyRange = IDBKeyRange.only("寻梦环游记"), list = [];
var index = db
.transaction('movies')
.objectStore('movies').index('title');
index.openCursor(singleKeyRange, 'prevunique').onsuccess = function(event) {
var cursor = event.target.result;
if (cursor) {
console.log('cursor.value:', cursor.value);
list.push(cursor.value);
cursor.continue();
} else {
    console.log('list:', list);
}
};

澳门新浦京娱乐场网站 28

七、关闭和删除数据库

  • 关门数据库只须求在数据库对象db上调用close()措施就可以
db.close();

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f37afae779476637224-1">
1
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f37afae779476637224-1" class="crayon-line">
db.close();
</div>
</div></td>
</tr>
</tbody>
</table>


关闭数据库后,`db`对象仍然保存着该数据库的相关信息,只是无法再开启事务(调用开启事务方法会报错,提示数据库连接已断开):

澳门新浦京娱乐场网站 29

  • 删除数据库则需求选取indexedDB.deleteDatabase(dbName)方法
JavaScript

window.indexedDB.deleteDatabase(dbName);

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f37afae77e452573671-1">
1
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f37afae77e452573671-1" class="crayon-line">
window.indexedDB.deleteDatabase(dbName);
</div>
</div></td>
</tr>
</tbody>
</table>

8、indexedDB的局限性

以下情形不适合选用IndexedDB

  • 天下三种语言混合存款和储蓄。国际化帮助不佳。须求和谐解和管理理。
  • 和劳务器端数据库同步。你得投机写同步代码。
  • 全文字笔迹查验索。

瞩目,在偏下意况下,数据库大概被解除:

  • 用户请求解除数据。
  • 浏览器处于隐私方式。最终退出浏览器的时候,数据会被破除。
  • 硬盘等存款和储蓄设备的容积到限。
  • 不科学的
  • 不完整的更换.

总结

  1. 使用indexedDB.open(dbName, version)张开二个数据库连接
  2. 使用indexedDB.deleteDatabase(dbName)删去1个数据库
  3. 在数据库对象db上使用createObjectStore(storeName, config)成立对象存款和储蓄空间
  4. 在对象存款和储蓄空间objectStore上使用createIndex(indexName, keyName, config)创造索引
  5. 对数据库的操作都供给通过事务完成: var transction = db.transaction([storeName], mode)
  6. 数据库的增加和删除改查均通过objectStore指标实现,var objectStore = transaction.objectStore(storeName)
  7. 对数据库数据操作有: add()get()delete()put等方法
  8. 追寻数据足以选择索引: objectStore.index(indexName)
  9. 遍历和过滤数据足以行使游标: openCursor(keyRange, direction)

参照链接

  • IndexedDB的基本概念-MDN
  • 使用 IndexedDB-MDN
  • IndexedDB API接口-MDN
  • Indexed Database API 2.0 – w3c

    1 赞 2 收藏 1 评论

澳门新浦京娱乐场网站 30

本文由澳门新浦京娱乐场网站发布于新浦京娱乐场官网,转载请注明出处:主导使用,加载品质优化