请选择 进入手机版 | 继续访问电脑版
设为首页收藏本站

QQ登录

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

切换风格 注册 找回密码

html5源码-html5教程网


查看: 27842|回复: 15

HTML5 离线存储之Web SQL

[复制链接]

10

主题

0

听众

34

积分

版主

Rank: 7Rank: 7Rank: 7

贡献
0
金钱
4

社区QQ达人

发表于 2016-3-26 16:09:44 |显示全部楼层
HTML5 在离线存储之Web SQL
本篇没有考虑异步,多线程及SQL注入
WebDatabase 规范中说这份规范不再维护了,原因是同质化(几乎实现者都选择了Sqlite),
且不说这些,单看在HTML5中如何实现离线数据的CRUD,最基本的用法(入门级别)

1,打开数据库
2,创建表
3,新增数据
4,更新数据
5,读取数据
6,删除数据

事实上,关键点在于如何拿到一个可执行SQL语句的上下文,
像创建表,删除表,CRUD操作等仅区别于SQL语句的写法.OK,貌似"SqlHelper"啊,换个名字,dataBaseOperator就它了
executeReader,executeScalar两个方法与executeNonQuery严重同质,
下边的代码产生定义了我们的dataBaseOperator"类",第二行
3-5行则定义打开数据库连接方法,"类方法",效果类似C#中的静态方法,直接类名.方法调用
6-15行则定义executeNonQuery方法,意指查询数据库,与executeReader方法和executeScalar方法同质,均可返回记录集
整个 dataBaseOperator就完整了,很简单,唯一要指出的是,测试以下代码时请选择一个支持HTML5的浏览器!如Google Chrome
  1. //TODO;SQL注入
  2. function dataBaseOperator() {};
  3. dataBaseOperator.openDatabase = function () {
  4.     return window.openDatabase("dataBaseUserStories", "1.0", "dataBase used for user stories", 2 * 1024 * 1024);
  5. }
  6. dataBaseOperator.executeNonQuery = function (sql, parameters, callback) {
  7.     var db = this.openDatabase();
  8.     db.transaction(function (trans) {
  9.         trans.executeSql(sql, parameters, function (trans, result) {
  10.             callback(result);
  11.         }, function (trans, error) {
  12.             throw error.message;
  13.         });
  14.     });
  15. }
  16. dataBaseOperator.executeReader = dataBaseOperator.executeNonQuery;
  17. dataBaseOperator.executeScalar = dataBaseOperator.executeNonQuery;
复制代码
有了"SqlHeper",再看业务处理层(Business Logic Layer)
业务处理类包括了创建表,删除表,新增记录,删除记录以及读取记录,这里没有写更新,实际上先删后增一样滴,即使要写也不复杂
  1. function userStoryProvider() {
  2.     this.createUserStoryTable = function () {
  3.         dataBaseOperator.executeNonQuery("CREATE TABLE tbUserStories(id integer primary key autoincrement,role,ability,benefit,name,importance,estimate,notes)");
  4.     };
  5.     this.dropUserStoryTable = function () {
  6.         dataBaseOperator.executeNonQuery("DROP TABLE tbUserStories");
  7.     };
  8.     this.addUserStory = function (role, ability, benefit, name, importance, estimate, notes) {
  9.         dataBaseOperator.executeNonQuery("INSERT INTO tbUserStories(role,ability,benefit,name,importance,estimate,notes) SELECT ?,?,?,?,?,?,?",
  10.              [role, ability, benefit, name, importance, estimate, notes], function (result) {
  11.                  //alert("rowsAffected:" + result.rowsAffected);
  12.               });
  13.     };
  14.     this.removeUserStory = function (id) {
  15.         dataBaseOperator.executeNonQuery("DELETE FROM tbUserStories WHERE id = ?", [id], function (result) {
  16.             //alert("rowsAffected:" + result.rowsAffected);
  17.          });
  18.     };
  19.     this.loadUserStories = function (callback) {
  20.         dataBaseOperator.executeReader("SELECT * FROM tbUserStories", [], function (result) {
  21.             callback(result);
  22.         });
  23.         //result.insertId,result.rowsAffected,result.rows
  24.      };
  25. }
复制代码
createUserStoryTable,dropUserStoryTable,addUserStory,removeUserStory又是严重同质,不说了,仅SQL语句不同而已
但loadUserStories与上述四个方法均不同,是因为它把SQLResultSetRowList返回给了调用者,这里仍然是简单的"转发",
页面在使用的时候需要首先创建provider实例(使用类似C#中的类实例上的方法调用)
1 var _userStoryProvider = new userStoryProvider();
之后就可以调用该实例的方法了,仅举个例子,具体代码省去
  1. function loadUserStory() {
  2.     try {
  3.         _userStoryProvider.loadUserStories(function (result) {
  4.             var _userStories = new Array();
  5.             for (var i = 0; i < result.rows.length; i++) {
  6.                 var o = result.rows.item(i);
  7.                 var _userStory = new userStory(o.id, o.name, o.role, o.ability, o.benefit, o.importance, o.estimate, o.notes);
  8.                 _userStories.push(_userStory);
  9.             }
  10. //...
  11.     } catch (error) {
  12.         alert("_userStoryProvider.loadUserStories:" + error);
  13.     }
  14. }
复制代码
得到_userStories这个数组后,就没有下文了,是自动创建HTML还是绑定到EXT,发挥想象力吧...继续
userStory是一个自定义的"Model" "类"
  1. function userStory(id, name, role, ability, benefit, importance, estimate, notes) {
  2.     this.id = id;
  3.     this.name = name;
  4.     this.role = role;
  5.     this.ability = ability;
  6.     this.benefit = benefit;
  7.     this.importance = importance;
  8.     this.estimate = estimate;
  9.     this.notes = notes;
  10. };
复制代码
最后贴出应用的代码,业务相关的代码,不看也罢,谁家与谁家的都不同
  1. /*
  2.     http://stackoverflow.com/questions/2010892/storing-objects-in-html5-localstorage
  3.     http://www.w3.org/TR/webdatabase/#sqlresultset
  4.     http://html5doctor.com/introducing-web-sql-databases/
  5.     http://stackoverflow.com/questions/844885/sqlite-insert-into-with-unique-names-getting-id
  6. */
  7. var _userStoryProvider = new userStoryProvider();
  8. $(document).ready(function () {
  9.     loadUserStory();

  10.     /* 添加用户故事 */
  11.     $("#btnAdd").click(function () {
  12.         var item = { role: $("#role").val(), ability: $("#ability").val(), benefit: $("#benefit").val(), name: $("#Name").val(), importance: $("#Importance").val(), estimate: $("#Estimate").val(), notes: $("#Notes").val() };
  13.         try {
  14.             _userStoryProvider.addUserStory(item.role, item.ability, item.benefit, item.name, item.importance, item.estimate, item.notes);
  15.             loadUserStory();
  16.         } catch (error) {
  17.             alert("_userStoryProvider.addUserStory:" + error);
  18.         }
  19.     });

  20.     /* 创建用户故事表 */
  21.     $("#btnCreateTable").click(function () {
  22.         try {
  23.             _userStoryProvider.createUserStoryTable();
  24.         } catch (error) {
  25.             alert("_userStoryProvider.createUserStoryTable:" + error);
  26.         }
  27.     });

  28.     /* 删除用户故事表 */
  29.     $("#btnDropTable").click(function () {
  30.         try {
  31.             _userStoryProvider.dropUserStoryTable();
  32.         } catch (error) {
  33.             alert("_userStoryProvider.dropUserStoryTable:" + error);
  34.         }
  35.     });
  36. });

  37. /* 加载用户故事 */
  38. function loadUserStory() {
  39.     try {
  40.         _userStoryProvider.loadUserStories(function (result) {
  41.             var _userStories = new Array();
  42.             for (var i = 0; i < result.rows.length; i++) {
  43.                 var o = result.rows.item(i);
  44.                 var _userStory = new userStory(o.id, o.name, o.role, o.ability, o.benefit, o.importance, o.estimate, o.notes);
  45.                 _userStories.push(_userStory);
  46.             }

  47.             if (!_userStories) return;
  48.             var table = document.getElementById("user_story_table");
  49.             if (!table) return;
  50.             var _trs = table.getElementsByTagName("tr");
  51.             var _len = _trs.length;
  52.             for (var i = 0; i < _len; i++) {
  53.                 table.removeChild(_trs[i]);
  54.             }
  55.             {
  56.                 var tr = document.createElement("tr");
  57.                 tr.setAttribute("class", "product_backlog_row header");
  58.                 {
  59.                     tr.appendChild(CreateTd("id", "id"));
  60.                     tr.appendChild(CreateTd("name", "name"));
  61.                     tr.appendChild(CreateTd("importance", "importance"));
  62.                     tr.appendChild(CreateTd("estimate", "estimate"));
  63.                     tr.appendChild(CreateTd("description", "role"));
  64.                     tr.appendChild(CreateTd("notes", "notes"));
  65.                     tr.appendChild(CreateTd("delete", "delete"));
  66.                 };
  67.                 table.appendChild(tr);
  68.             }
  69.             for (var i = 0; i < _userStories.length; i++) {
  70.                 CreateRow(table, _userStories[i]);
  71.             }
  72.         });
  73.     } catch (error) {
  74.         alert("_userStoryProvider.loadUserStories:" + error);
  75.     }
  76. }
  77. function CreateRow(table, userStory) {
  78.     if (!table) return;
  79.     if (!userStory) return;
  80.     {
  81.         var tr = document.createElement("tr");
  82.         tr.setAttribute("class", "product_backlog_row");
  83.         {
  84.             tr.appendChild(CreateTd("id", userStory.id));
  85.             tr.appendChild(CreateTd("name", userStory.name));
  86.             tr.appendChild(CreateTd("importance", userStory.importance));
  87.             tr.appendChild(CreateTd("estimate", userStory.estimate));
  88.             tr.appendChild(CreateTd("description", userStory.role));
  89.             tr.appendChild(CreateTd("notes", userStory.notes));
  90.             tr.appendChild(CreateDeleteButton("delete_button", userStory.id));
  91.         };
  92.         table.appendChild(tr);
  93.     }
  94. }
  95. function CreateTd(name, value) {
  96.     var td = document.createElement("td");
  97.     td.setAttribute("class", "user_story " + name);
  98.     td.innerText = value;
  99.     return td;
  100. };
  101. function CreateDeleteButton(name, id) {
  102.     var td = document.createElement("td");
  103.     td.setAttribute("class", "user_story " + name);
  104.     /* 删除用户故事 */
  105.     td.innerHTML = "<a href=\"###\" title=\"delete\" onclick=\"javascript:_userStoryProvider.removeUserStory(\'" + id + "');removeRow(this);\">>>delete</a>";
  106.     return td;
  107. }
  108. function removeRow(obj) {
  109.     document.getElementById("user_story_table").deleteRow(obj.parentNode.parentNode.rowIndex);
  110.     //obj.parentNode.parentNode.removeNode(true);
  111. }
复制代码
有一个小例子,点这里下载(占位,有点小毛病改好就放)
看完代码复习下基本功课
1,WindowDatabase接口,注意openDatabase方法
  1. [Supplemental, NoInterfaceObject]
  2. interface WindowDatabase {
  3.   Database openDatabase(in DOMString name, in DOMString version, in DOMString displayName, in unsigned long estimatedSize, in optional DatabaseCallback creationCallback);
  4. };
  5. Window implements WindowDatabase;

  6. [Supplemental, NoInterfaceObject]
  7. interface WorkerUtilsDatabase {
  8.   Database openDatabase(in DOMString name, in DOMString version, in DOMString displayName, in unsigned long estimatedSize, in optional DatabaseCallback creationCallback);
  9.   DatabaseSync openDatabaseSync(in DOMString name, in DOMString version, in DOMString displayName, in unsigned long estimatedSize, in optional DatabaseCallback creationCallback);
  10. };
  11. WorkerUtils implements WorkerUtilsDatabase;

  12. [Callback=FunctionOnly, NoInterfaceObject]
  13. interface DatabaseCallback {
  14.   void handleEvent(in Database database);
  15. };
复制代码
2,SQLTransaction接口,关注executeSql方法
  1. typedef sequence<any> ObjectArray;

  2. interface SQLTransaction {
  3.   void executeSql(in DOMString sqlStatement, in optional ObjectArray arguments, in optional SQLStatementCallback callback, in optional SQLStatementErrorCallback errorCallback);
  4. };

  5. [Callback=FunctionOnly, NoInterfaceObject]
  6. interface SQLStatementCallback {
  7.   void handleEvent(in SQLTransaction transaction, in SQLResultSet resultSet);
  8. };

  9. [Callback=FunctionOnly, NoInterfaceObject]
  10. interface SQLStatementErrorCallback {
  11.   boolean handleEvent(in SQLTransaction transaction, in SQLError error);
  12. };
复制代码
3,最后看下SQLResultSetRowList定义
interface SQLResultSetRowList {
readonly attribute unsigned long length;
getter any item(in unsigned long index);
};

和SQLResultSet定义
  1. interface SQLResultSet {
  2. readonly attribute long insertId;
  3. readonly attribute long rowsAffected;
  4. readonly attribute SQLResultSetRowList rows;
  5. };
复制代码
类图

由于window对象实现了WindowDatabase接口,从而可以直接在window对象上调用openDatabase等方法
同时实现WindowDatabse接口的还有WorkerUtils对象

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册 新浪微博登陆

0

主题

0

听众

19

积分

新手上路

Rank: 1

贡献
0
金钱
0
发表于 2016-3-26 16:50:48 |显示全部楼层
看看真假。。。
回复

使用道具 举报

0

主题

0

听众

39

积分

新手上路

Rank: 1

贡献
0
金钱
0
发表于 2016-3-30 00:21:29 |显示全部楼层
一直在看
回复

使用道具 举报

0

主题

0

听众

25

积分

新手上路

Rank: 1

贡献
0
金钱
0
发表于 2016-3-30 00:22:35 |显示全部楼层
报告!别开枪,我就是路过来看看的。。。
回复

使用道具 举报

2

主题

1

听众

47

积分

新手上路

Rank: 1

贡献
0
金钱
2
发表于 2016-3-30 06:50:46 |显示全部楼层
做的 很漂亮啊~ 喜欢~
回复

使用道具 举报

0

主题

0

听众

19

积分

新手上路

Rank: 1

贡献
0
金钱
0
发表于 2016-3-31 15:47:01 |显示全部楼层
看到了不错啊
回复

使用道具 举报

1

主题

0

听众

58

积分

注册会员

Rank: 2

贡献
0
金钱
1
发表于 2016-3-31 23:26:14 |显示全部楼层
不错哦 真 的很实用
回复

使用道具 举报

0

主题

0

听众

49

积分

新手上路

Rank: 1

贡献
0
金钱
0
发表于 2016-3-31 23:51:31 |显示全部楼层
边撸边过
回复

使用道具 举报

0

主题

0

听众

8

积分

新手上路

Rank: 1

贡献
0
金钱
0
发表于 2016-4-4 21:25:19 |显示全部楼层
好东西 我来看看
回复

使用道具 举报

0

主题

0

听众

29

积分

新手上路

Rank: 1

贡献
0
金钱
0
发表于 2016-4-9 13:29:00 |显示全部楼层
支持哥们  我们菜鸟很喜欢这个
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆



Archiver|手机版|     

HTML5教程网 Powered by Discuz! X2.5

© 2001-2012 Comsenz Inc.

回顶部