HTML 5离线存储之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
<ol class="dp-xml"> <li class="alt"><span><span>//TODO;SQL注入 </span></span></li> <li><span> function dataBaseOperator() {}; </span></li> <li class="alt"> <span> </span><span class="attribute">dataBaseOperator.openDatabase</span><span> = </span><span class="attribute-value">function</span><span> () { </span> </li> <li><span> return window.openDatabase("dataBaseUserStories", "1.0", "dataBase used for user stories", 2 * 1024 * 1024); </span></li> <li class="alt"><span> } </span></li> <li> <span> </span><span class="attribute">dataBaseOperator.executeNonQuery</span><span> = </span><span class="attribute-value">function</span><span> (sql, parameters, callback) { </span> </li> <li class="alt"> <span> var </span><span class="attribute">db</span><span> = </span><span class="attribute-value">this</span><span>.openDatabase(); </span> </li> <li><span> db.transaction(function (trans) { </span></li> <li class="alt"><span> trans.executeSql(sql, parameters, function (trans, result) { </span></li> <li><span> callback(result); </span></li> <li class="alt"><span> }, function (trans, error) { </span></li> <li><span> throw error.message; </span></li> <li class="alt"><span> }); </span></li> <li><span> }); </span></li> <li class="alt"><span> } </span></li> <li> <span> </span><span class="attribute-value">dataBaseOperator</span><span class="attribute">dataBaseOperator.executeReader</span><span> = dataBaseOperator.executeNonQuery; </span> </li> <li class="alt"> <span> </span><span class="attribute-value">dataBaseOperator</span><span class="attribute">dataBaseOperator.executeScalar</span><span> = dataBaseOperator.executeNonQuery; </span> </li> </ol>
有了"SqlHeper",再看业务处理层(Business Logic Layer)
业务处理类包括了创建表,删除表,新增记录,删除记录以及读取记录,这里没有写更新,实际上先删后增一样滴,即使要写也不复杂
<ol class="dp-xml"> <li class="alt"><span><span>function userStoryProvider() { </span></span></li> <li> <span> </span><span class="attribute">this.createUserStoryTable</span><span> = </span><span class="attribute-value">function</span><span> () { </span> </li> <li class="alt"><span> dataBaseOperator.executeNonQuery("CREATE TABLE tbUserStories(id integer primary key autoincrement,role,ability,benefit,name,importance,estimate,notes)"); </span></li> <li><span> }; </span></li> <li class="alt"> <span> </span><span class="attribute">this.dropUserStoryTable</span><span> = </span><span class="attribute-value">function</span><span> () { </span> </li> <li><span> dataBaseOperator.executeNonQuery("DROP TABLE tbUserStories"); </span></li> <li class="alt"><span> }; </span></li> <li> <span> </span><span class="attribute">this.addUserStory</span><span> = </span><span class="attribute-value">function</span><span> (role, ability, benefit, name, importance, estimate, notes) { </span> </li> <li class="alt"><span> dataBaseOperator.executeNonQuery("INSERT INTO tbUserStories(role,ability,benefit,name,importance,estimate,notes) SELECT ?,?,?,?,?,?,?", </span></li> <li><span> [role, ability, benefit, name, importance, estimate, notes], function (result) { </span></li> <li class="alt"><span> //alert("rowsAffected:" + result.rowsAffected); </span></li> <li><span> }); </span></li> <li class="alt"><span> }; </span></li> <li> <span> </span><span class="attribute">this.removeUserStory</span><span> = </span><span class="attribute-value">function</span><span> (id) { </span> </li> <li class="alt"> <span> dataBaseOperator.executeNonQuery("DELETE FROM tbUserStories WHERE </span><span class="attribute">id</span><span> = ?", [id], function (result) { </span> </li> <li><span> //alert("rowsAffected:" + result.rowsAffected); </span></li> <li class="alt"><span> }); </span></li> <li><span> }; </span></li> <li class="alt"> <span> </span><span class="attribute">this.loadUserStories</span><span> = </span><span class="attribute-value">function</span><span> (callback) { </span> </li> <li><span> dataBaseOperator.executeReader("SELECT * FROM tbUserStories", [], function (result) { </span></li> <li class="alt"><span> callback(result); </span></li> <li><span> }); </span></li> <li class="alt"><span> //result.insertId,result.rowsAffected,result.rows24 }; </span></li> <li><span> } </span></li> </ol>
createUserStoryTable,dropUserStoryTable,addUserStory,removeUserStory又是严重同质,不说了,仅SQL语句不同而已
但loadUserStories与上述四个方法均不同,是因为它把SQLResultSetRowList返回给了调用者,这里仍然是简单的"转发",页面在使用的时候需要首先创建provider实例(使用类似C#中的类实例上的方法调用)
<ol class="dp-xml"><li class="alt"><span><span>var </span><span class="attribute">_userStoryProvider</span><span> = </span><span class="attribute-value">new</span><span> userStoryProvider(); </span></span></li></ol>
之后就可以调用该实例的方法了,仅举个例子,具体代码省去
<ol class="dp-xml"> <li class="alt"><span><span>function loadUserStory() { </span></span></li> <li><span>try { </span></li> <li class="alt"><span>_userStoryProvider.loadUserStories(function (result) { </span></li> <li> <span> var </span><span class="attribute">_userStories</span><span> = </span><span class="attribute-value">new</span><span> Array(); </span> </li> <li class="alt"> <span>for (var </span><span class="attribute">i</span><span> = </span><span class="attribute-value">0</span><span>; i </span><span class="tag"><</span><span> </span><span class="tag-name">result.rows.length</span><span>; i++) { </span></li><li><span> var </span><span class="attribute">o</span><span> = </span><span class="attribute-value">result</span><span>.rows.item(i); </span></li><li class="alt"><span> var </span><span class="attribute">_userStory</span><span> = </span><span class="attribute-value">new</span><span> userStory(o.id, o.name, o.role, o.ability, o.benefit, o.importance, o.estimate, o.notes); </span></li><li><span> _userStories.push(_userStory); </span></li><li class="alt"><span> }//... </span></li><li><span>} catch (error) { </span></li><li class="alt"><span> alert("_userStoryProvider.loadUserStories:" + error); </span></li><li><span>}} </span></li></ol>
得到_userStories这个数组后,就没有下文了,是自动创建HTML还是绑定到EXT,发挥想象力吧...继续
userStory是一个自定义的"Model" "类"·
<ol class="dp-xml"><li class="alt"><span><span>function userStory(id, name, role, ability, benefit, importance, estimate, notes) { </span></span></li><li><span> </span><span class="attribute">this.id</span><span> = id; </span></li><li class="alt"><span> </span><span class="attribute">this.name</span><span> = name; </span></li><li><span> </span><span class="attribute">this.role</span><span> = role; </span></li><li class="alt"><span> </span><span class="attribute">this.ability</span><span> = ability; </span></li><li><span> </span><span class="attribute">this.benefit</span><span> = benefit; </span></li><li class="alt"><span> </span><span class="attribute">this.importance</span><span> = importance; </span></li><li><span> </span><span class="attribute">this.estimate</span><span> = estimate; </span></li><li class="alt"><span> </span><span class="attribute">this.notes</span><span> = notes; </span></li><li><span> }; </span></li></ol>
最后贴出应用的代码,业务相关的代码,不看也罢,谁家与谁家的都不同
<ol class="dp-xml"><li class="alt"><span><span>/* </span></span></li><li><span> http://stackoverflow.com/questions/2010892/storing-objects-in-html5-localstorage </span></li><li class="alt"><span> http://www.w3.org/TR/webdatabase/#sqlresultset </span></li><li><span> http://html5doctor.com/introducing-web-sql-databases/ </span></li><li class="alt"><span> http://stackoverflow.com/questions/844885/sqlite-insert-into-with-unique-names-getting-id </span></li><li><span> */ </span></li><li class="alt"><span> var </span><span class="attribute">_userStoryProvider</span><span> = </span><span class="attribute-value">new</span><span> userStoryProvider(); </span></li><li><span> $(document).ready(function () { </span></li><li class="alt"><span> loadUserStory(); </span></li><li><span> </span></li><li class="alt"><span> /* 添加用户故事 */ </span></li><li><span> $("#btnAdd").click(function () { </span></li><li class="alt"><span> var </span><span class="attribute">item</span><span> = { role: $("#role").val(), ability: $("#ability").val(), benefit: $("#benefit").val(), name: $("#Name").val(), importance: $("#Importance").val(), estimate: $("#Estimate").val(), notes: $("#Notes").val() }; </span></li><li><span> try { </span></li><li class="alt"><span> _userStoryProvider.addUserStory(item.role, item.ability, item.benefit, item.name, item.importance, item.estimate, item.notes); </span></li><li><span> loadUserStory(); </span></li><li class="alt"><span> } catch (error) { </span></li><li><span> alert("_userStoryProvider.addUserStory:" + error); </span></li><li class="alt"><span> } </span></li><li><span> }); </span></li><li class="alt"><span> </span></li><li><span> /* 创建用户故事表 */ </span></li><li class="alt"><span> $("#btnCreateTable").click(function () { try { </span></li><li><span> _userStoryProvider.createUserStoryTable(); </span></li><li class="alt"><span> } catch (error) { </span></li><li><span> alert("_userStoryProvider.createUserStoryTable:" + error); </span></li><li class="alt"><span> } </span></li><li><span> }); </span></li><li class="alt"><span> </span></li><li><span> /* 删除用户故事表 */ </span></li><li class="alt"><span> $("#btnDropTable").click(function () { </span></li><li><span> try { </span></li><li class="alt"><span> _userStoryProvider.dropUserStoryTable(); </span></li><li><span> } catch (error) { </span></li><li class="alt"><span> alert("_userStoryProvider.dropUserStoryTable:" + error); </span></li><li><span> } </span></li><li class="alt"><span> }); </span></li><li><span> }); </span></li><li class="alt"><span> </span></li><li><span> /* 加载用户故事 */ </span></li><li class="alt"><span> function loadUserStory() { </span></li><li><span> try { </span></li><li class="alt"><span> _userStoryProvider.loadUserStories(function (result) { </span></li><li><span> var </span><span class="attribute">_userStories</span><span> = </span><span class="attribute-value">new</span><span> Array(); </span></li><li class="alt"><span> for (var </span><span class="attribute">i</span><span> = </span><span class="attribute-value">0</span><span>; i </span><span class="tag"><</span><span> </span><span class="tag-name">result.rows.length</span><span>; i++) { </span></li><li><span> var </span><span class="attribute">o</span><span> = </span><span class="attribute-value">result</span><span>.rows.item(i); </span></li><li class="alt"><span> var </span><span class="attribute">_userStory</span><span> = </span><span class="attribute-value">new</span><span> userStory(o.id, o.name, o.role, o.ability, o.benefit, o.importance, o.estimate, o.notes); </span></li><li><span> _userStories.push(_userStory); </span></li><li class="alt"><span> } </span></li><li><span> </span></li><li class="alt"><span> if (!_userStories) return; </span></li><li><span> var </span><span class="attribute">table</span><span> = </span><span class="attribute-value">document</span><span>.getElementById("user_story_table"); </span></li><li class="alt"><span> if (!table) return; </span></li><li><span> var </span><span class="attribute">_trs</span><span> = </span><span class="attribute-value">table</span><span>.getElementsByTagName("tr"); </span></li><li class="alt"><span> var </span><span class="attribute">_len</span><span> = </span><span class="attribute-value">_trs</span><span>.length; </span></li><li><span> for (var </span><span class="attribute">i</span><span> = </span><span class="attribute-value">0</span><span>; i </span><span class="tag"><</span><span> </span><span class="tag-name">_len</span><span>; i++) { </span></li><li class="alt"><span> table.removeChild(_trs[i]); </span></li><li><span> } </span></li><li class="alt"><span> { </span></li><li><span> var </span><span class="attribute">tr</span><span> = </span><span class="attribute-value">document</span><span>.createElement("tr"); </span></li><li class="alt"><span> tr.setAttribute("class", "product_backlog_row header"); </span></li><li><span> { </span></li><li class="alt"><span> tr.appendChild(CreateTd("id", "id")); </span></li><li><span> tr.appendChild(CreateTd("name", "name")); </span></li><li class="alt"><span> tr.appendChild(CreateTd("importance", "importance")); </span></li><li><span> tr.appendChild(CreateTd("estimate", "estimate")); </span></li><li class="alt"><span> tr.appendChild(CreateTd("description", "role")); </span></li><li><span> tr.appendChild(CreateTd("notes", "notes")); </span></li><li class="alt"><span> tr.appendChild(CreateTd("delete", "delete")); </span></li><li><span> }; </span></li><li class="alt"><span> table.appendChild(tr); </span></li><li><span> } </span></li><li class="alt"><span> for (var </span><span class="attribute">i</span><span> = </span><span class="attribute-value">0</span><span>; i </span><span class="tag"><</span><span> </span><span class="tag-name">_userStories.length</span><span>; i++) { </span></li><li><span> CreateRow(table, _userStories[i]); </span></li><li class="alt"><span> } </span></li><li><span> }); </span></li><li class="alt"><span> } catch (error) { </span></li><li><span> alert("_userStoryProvider.loadUserStories:" + error); </span></li><li class="alt"><span> } </span></li><li><span> } </span></li><li class="alt"><span> function CreateRow(table, userStory) { </span></li><li><span> if (!table) return; </span></li><li class="alt"><span> if (!userStory) return; </span></li><li><span> { </span></li><li class="alt"><span> var </span><span class="attribute">tr</span><span> = </span><span class="attribute-value">document</span><span>.createElement("tr"); </span></li><li><span> tr.setAttribute("class", "product_backlog_row"); </span></li><li class="alt"><span> { </span></li><li><span> tr.appendChild(CreateTd("id", userStory.id)); </span></li><li class="alt"><span> tr.appendChild(CreateTd("name", userStory.name)); </span></li><li><span> tr.appendChild(CreateTd("importance", userStory.importance)); </span></li><li class="alt"><span> tr.appendChild(CreateTd("estimate", userStory.estimate)); </span></li><li><span> tr.appendChild(CreateTd("description", userStory.role)); </span></li><li class="alt"><span> tr.appendChild(CreateTd("notes", userStory.notes)); </span></li><li><span> tr.appendChild(CreateDeleteButton("delete_button", userStory.id)); </span></li><li class="alt"><span> }; </span></li><li><span> table.appendChild(tr); </span></li><li class="alt"><span> } </span></li><li><span> } </span></li><li class="alt"><span> function CreateTd(name, value) { </span></li><li><span> var </span><span class="attribute">td</span><span> = </span><span class="attribute-value">document</span><span>.createElement("td"); </span></li><li class="alt"><span> td.setAttribute("class", "user_story " + name); </span></li><li><span> </span><span class="attribute">td.innerText</span><span> = </span><span class="attribute-value">value</span><span>; </span></li><li class="alt"><span> return td; </span></li><li><span> }; </span></li><li class="alt"><span> function CreateDeleteButton(name, id) { </span></li><li><span> var </span><span class="attribute">td</span><span> = </span><span class="attribute-value">document</span><span>.createElement("td"); </span></li><li class="alt"><span> td.setAttribute("class", "user_story " + name); </span></li><li><span> /* 删除用户故事 */ </span></li><li class="alt"><span> </span><span class="attribute">td.innerHTML</span><span> = </span><span class="attribute-value">"<a href=\"</span><span>###\" </span><span class="attribute">title</span><span>=\"delete\" </span><span class="attribute">onclick</span><span>=\"javascript:_userStoryProvider.removeUserStory(\'" + id + "');removeRow(this);\"</span><span class="tag">></span><span class="tag">></span><span class="tag">></span><span>delete</span><span class="tag"></</span><span class="tag-name">a</span><span class="tag">></span><span>"; </span> </li> <li><span> return td; </span></li> <li class="alt"><span> } </span></li> <li><span> function removeRow(obj) { </span></li> <li class="alt"><span> document.getElementById("user_story_table").deleteRow(obj.parentNode.parentNode.rowIndex); </span></li> <li><span> //obj.parentNode.parentNode.removeNode(true); </span></li> <li class="alt"><span> } </span></li> </ol>
看完代码复习下基本功课
1,WindowDatabase接口,注意openDatabase方法
<ol class="dp-xml"> <li class="alt"><span><span>[Supplemental, NoInterfaceObject] </span></span></li> <li><span>interface WindowDatabase { </span></li> <li class="alt"><span> Database openDatabase(in DOMString name, in DOMString version, in DOMString displayName, in unsigned long estimatedSize, in optional DatabaseCallback creationCallback);}; </span></li> <li><span>Window implements WindowDatabase; </span></li> <li class="alt"><span>[Supplemental, NoInterfaceObject] </span></li> <li><span>interface WorkerUtilsDatabase { </span></li> <li class="alt"><span> Database openDatabase(in DOMString name, in DOMString version, in DOMString displayName, in unsigned long estimatedSize, in optional DatabaseCallback creationCallback); DatabaseSync openDatabaseSync(in DOMString name, in DOMString version, in DOMString displayName, in unsigned long estimatedSize, in optional DatabaseCallback creationCallback);}; </span></li> <li><span>WorkerUtils implements WorkerUtilsDatabase; </span></li> <li class="alt"> <span>[</span><span class="attribute">Callback</span><span>=</span><span class="attribute-value">FunctionOnly</span><span>, NoInterfaceObject] </span> </li> <li><span>interface DatabaseCallback { </span></li> <li class="alt"><span>void handleEvent(in Database database); </span></li> <li><span>}; </span></li> </ol>
2,SQLTransaction接口,关注executeSql方法
<ol class="dp-xml"> <li class="alt"><span><span>typedef sequence</span><span class="tag"><</span><span class="tag-name">any</span><span class="tag">></span><span> ObjectArray; </span></span></li> <li><span>interface SQLTransaction { </span></li> <li class="alt"><span> void executeSql(in DOMString sqlStatement, in optional ObjectArray arguments, in optional SQLStatementCallback callback, in optional SQLStatementErrorCallback errorCallback);}; </span></li> <li> <span>[</span><span class="attribute">Callback</span><span>=</span><span class="attribute-value">FunctionOnly</span><span>, NoInterfaceObject] </span> </li> <li class="alt"><span>interface SQLStatementCallback { </span></li> <li><span> void handleEvent(in SQLTransaction transaction, in SQLResultSet resultSet);}; </span></li> <li class="alt"> <span>[</span><span class="attribute">Callback</span><span>=</span><span class="attribute-value">FunctionOnly</span><span>, NoInterfaceObject] </span> </li> <li><span>interface SQLStatementErrorCallback { </span></li> <li class="alt"><span> boolean handleEvent(in SQLTransaction transaction, in SQLError error); </span></li> <li><span>}; </span></li> </ol>
3,最后看下SQLResultSetRowList定义
<ol class="dp-xml"> <li class="alt"><span><span>interface SQLResultSetRowList { </span></span></li> <li><span> readonly attribute unsigned long length; </span></li> <li class="alt"><span>getter any item(in unsigned long index); </span></li> <li><span>}; </span></li> </ol>
和SQLResultSet定义
<ol class="dp-xml"> <li class="alt"><span><span>interface SQLResultSet { </span></span></li> <li><span> readonly attribute long insertId; </span></li> <li class="alt"><span> readonly attribute long rowsAffected; </span></li> <li><span> readonly attribute SQLResultSetRowList rows; </span></li> <li class="alt"><span> }; <br></span></li> </ol>

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

H5referstoHTML5,apivotaltechnologyinwebdevelopment.1)HTML5introducesnewelementsandAPIsforrich,dynamicwebapplications.2)Itsupportsmultimediawithoutplugins,enhancinguserexperienceacrossdevices.3)SemanticelementsimprovecontentstructureandSEO.4)H5'srespo

Web标准和技术从HTML4、CSS2和简单的JavaScript演变至今,经历了显着的发展。 1)HTML5引入了Canvas、WebStorage等API,增强了Web应用的复杂性和互动性。 2)CSS3增加了动画和过渡功能,使页面效果更加丰富。 3)JavaScript通过Node.js和ES6的现代化语法,如箭头函数和类,提升了开发效率和代码可读性,这些变化推动了Web应用的性能优化和最佳实践的发展。

H5代码的最佳实践包括:1.使用正确的DOCTYPE声明和字符编码;2.采用语义化标签;3.减少HTTP请求;4.使用异步加载;5.优化图像。这些实践能提升网页的效率、可维护性和用户体验。

H5不仅仅是HTML5的简称,它代表了一个更广泛的现代网页开发技术生态:1.H5包括HTML5、CSS3、JavaScript及相关API和技术;2.它提供更丰富、互动、流畅的用户体验,能在多设备上无缝运行;3.使用H5技术栈可以创建响应式网页和复杂交互功能。

H5与HTML5指的是同一个东西,即HTML5。HTML5是HTML的第五个版本,带来了语义化标签、多媒体支持、画布与图形、离线存储与本地存储等新功能,提升了网页的表现力和交互性。

HTML5是构建现代网页的关键技术,提供了许多新元素和功能。1.HTML5引入了语义化元素如、、等,增强了网页结构和SEO。2.支持多媒体元素和,无需插件即可嵌入媒体。3.表单增强了新输入类型和验证属性,简化了验证过程。4.提供了离线和本地存储功能,提升了网页性能和用户体验。

HTML5代码由标签、元素和属性组成:1.标签定义内容类型,用尖括号包围,如。2.元素由开始标签、内容和结束标签组成,如内容。3.属性在开始标签中定义键值对,增强功能,如。这些是构建网页结构的基本单位。

H5通过多媒体支持、离线存储和性能优化提升网页用户体验。1)多媒体支持:H5的和元素简化开发,提升用户体验。2)离线存储:WebStorage和IndexedDB允许离线使用,提升体验。3)性能优化:WebWorkers和元素优化性能,减少带宽消耗。
