HTML5 学习笔记(三)——本地存储(LocalStorage、SessionStorage、Web SQL Database)
一、HTML4客户端存储
B/S架构的应用大量的信息存储在服务器端,客户端通过请求响应的方式从服务器获得数据,这样集中存储也会给服务器带来相应的压力,有些数据可以直接存储在客户端,传统的Web技术中会使用Cookie,但Cookie有一些缺点,为了说明这个缺点我们先看看当提交表单时会有那些信息会被浏览器收集后发送到服务器。
1.1、提交表单发送到服务器的信息
1)、带name的可用表单元素
2)、url
3)、客户端请求头部信息
4)、cookie
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <% //定义一个cookie对象 Cookie cookie=new Cookie("color", "blue"); //设置过期时间为365小时,以秒为单位 cookie.setMaxAge(60*60*365); //添加cookie response.addCookie(cookie); %> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> <title>提交表单测试</title> </head> <body> <form action="target.do?id=1" method="post"> <h2>提交表单测试</h2> <p> 名称:<input type="text" name="txtName" id="txtName1" /> </p> <p> 价格:<input type="text" name="txtPrice" id="txtPrice1" value="888" readonly="readonly"/> </p> <p> 数量:<input type="text" name="txtAmount" id="txtAmount1" value="999" disabled="disabled"/> </p> <input type="hidden" id="key" value="123445"> <input type="submit" value="提交" /> </form> </body> </html>
运行结果:
服务器在响应头部中声明要求客户端浏览器指定设置cookie color=blue的工作,且指定了过期时间,会将cookie信息记录在本地,查看结果如下:
当提交信息给服务器时cookie将收集后返回服务器,同时也会将url、带name可用的表单及请求头部信息如user-agent等,结果如下:
1.2、客户端本地存储概要
顾名思义客户端本地存储就是将信息存储在客户端电脑上,cookie就是一种典型的传统客户端存储,长期以来本地存储能力一直是桌面应用区别于Web应用的一个主要优势,作为Web应用程序而言,新一代的HTML标准对数据的本地存储提出了更高的要求。传统的Web数据存储方式一直来使用的是Cookie,但Cookie有以下缺陷:
a)、cookie会被附加在每个HTTP请求中,所以无形中增加了流量。
b)、由于在HTTP请求中的cookie是明文传递的,所以安全性成问题。
c)、Cookie的大小限制在4 KB左右,容量达不到要求。
HTML5中的Web Storage,称为Web本地存储,在Web客户端储存数据的功能,用键值对的形式保存数据,曾经属于HTML5的规范,目前已经被独立出来形成单独的规范体系。本地存储优势:
a)、统一的标准,兼容性高(IE8、各大浏览器支持)
b)、数据存储量大
c)、无需安装插件
d)、减少网络流量
e)、更加适合移动端
HTML5 提供了四种在客户端存储数据的新方法,即localStorage 、sessionStorage、globalStorage、Web Sql Database。 前面三个适用于存储较少的数据,而Web Sql Database适用于存储大型的,复杂的数据,我习惯把前面的三个称之为小存储。 IE8、Firefox3.6、Chrome5、Safari4、Opera10,事实证明各个浏览器在API方面的实现基本上一致,存在一定的兼容性问题,但不影响正常使用。
在chrome浏览器中可以使用开发者工具查看到各种不同的本地存储方式,如下图所示:
Web SQL Database 和 Indexed Database 都是在客户端存储大量结构化数据的解决方案。Web SQL Database 实现了传统的基于 SQL 语句的数据库操作,而 Indexed Database 实现了 NoSQL 的存储方式。
二、localStorage
localStorage:将数据保存在客户端本地的硬件设备(通常指硬盘,但也可以是其他硬件设备)中,即使浏览器被关闭了,该数据仍然存在,下次打开浏览器访问网站时仍然可以继续使用。
2.1、添加
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>localStorage 本地存储</title> </head> <body> <h2>localStorage 本地存储</h2> <button onclick="add_click()">添加</button> <script type="text/javascript"> function add_click() { //向本地存储中添加一个名为name,值为"手机"的key-value对象 localStorage.setItem("name","手机"); //办法2 localStorage["price"]=999.5; //办法3 localStorage.amount=1788; } </script> </body> </html>
运行结果:
2.2、取值
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>localStorage 本地存储</title> </head> <body> <h2>localStorage 本地存储</h2> <button onclick="add_click()">添加</button> <button onclick="get_click()">取值</button> <h3 id="msg"></h3> <a href="d02.html">d02.html</a> <script type="text/javascript"> var msg=document.getElementById("msg"); //添加 function add_click() { //向本地存储中添加一个名为name,值为"手机"的key-value对象 localStorage.setItem("name","手机"); //办法2 localStorage["price"]=999.5; //办法3 localStorage.amount=1788; } //取值 function get_click() { msg.innerHTML+=localStorage.getItem("name")+"<br/>"; msg.innerHTML+=localStorage["price"]+"<br/>"; msg.innerHTML+=localStorage.amount+"<br/>"; } </script> </body> </html>
运行结果:
2.3、修改
//修改 function update_click() { //如果不存在就添加,如果存在就修改 localStorage.setItem("name","iPhone 8 plus手机"); //修改办法2 localStorage["price"]=899.5; //修改办法3 localStorage.amount=100; }
运行结果:
2.4、删除
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>localStorage 本地存储</title> </head> <body> <h2>localStorage 本地存储</h2> <button onclick="add_click()">添加</button> <button onclick="get_click()">取值</button> <button onclick="update_click()">修改</button> <button onclick="delete_click()">删除</button> <h3 id="msg"></h3> <a href="d02.html">d02.html</a> <script type="text/javascript"> var msg=document.getElementById("msg"); //添加 function add_click() { //向本地存储中添加一个名为name,值为"手机"的key-value对象 localStorage.setItem("name","手机"); //添加办法2 localStorage["price"]=999.5; //添加办法3 localStorage.amount=1788; } //取值 function get_click() { msg.innerHTML+=localStorage.getItem("name")+"<br/>"; msg.innerHTML+=localStorage["price"]+"<br/>"; msg.innerHTML+=localStorage.amount+"<br/>"; } //修改 function update_click() { //如果不存在就添加,如果存在就修改 localStorage.setItem("name","iPhone 8 plus手机"); //修改办法2 localStorage["price"]=899.5; //修改办法3 localStorage.amount=100; } //删除 function delete_click() { //根据键删除 //localStorage.removeItem("price"); //删除所有 localStorage.clear(); } </script> </body> </html>
运行结果:
2.5、跨页面与跨域
当关闭浏览器,下次再打开时,值仍然存在。可以跨页面,不能跨域。我们在d01页面中添加了值,在d02页面中仍然可以访问,在整个同域下都可以访问。
2.6、存储位置与SQLite
localStorage与cookie不一样,它存储在一个数据库文件中,默认位置在:C:\Users\Administrator\AppData\Local\Google\Chrome\User Data\Default\databases\http_localhost_*
使用SQLite数据库管理工具,打开后看到的结果,这里以taobao存储客户端的localStorage为例:
提示:SQLite,是一款轻型的免费开源的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源的世界著名数据库管理系统来讲,它的处理速度比他们都快。SQLite第一个Alpha版本诞生于2000年5月。 至2015年已经有15个年头,SQLite也迎来了一个版本 SQLite 3已经发布。
SQLiteSpy管理工具下载:http://pan.baidu.com/s/1i5JQtBf
2.7、用途、练习与兼容性
所有需要将少量(不超过4M)数据存储在客户端的需求都适用,如密码,用户偏好(profile)等
登录成功后记录用户访问次数。
在IE8中测试通过
Firefox测试通过
三、sessionStorage
将数据临时保存在客户端session对象中。session对象就是会话对象,session中存储的数据独立于每个客户,该数据会随着浏览器的关闭而消失。
sessionStorage的操作api与localStorage基本一样,在不手动清除的情况下localStorage永久保存,而sessionStorage只是临时暂存。
3.1、sessionStorage使用
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>sessionStorage 本地存储</title> </head> <body> <h2>sessionStorage 本地存储</h2> <button onclick="add_click()">添加</button> <button onclick="get_click()">取值</button> <button onclick="update_click()">修改</button> <button onclick="delete_click()">删除</button> <h3 id="msg"></h3> <a href="d04.html">d04.html</a> <script type="text/javascript"> var msg=document.getElementById("msg"); //添加 function add_click() { //向本地存储中添加一个名为name,值为"手机"的key-value对象 sessionStorage.setItem("name","手机"); //添加办法2 sessionStorage["price"]=999.5; //添加办法3 sessionStorage.amount=1788; } //取值 function get_click() { msg.innerHTML+=sessionStorage.getItem("name")+"<br/>"; msg.innerHTML+=sessionStorage["price"]+"<br/>"; msg.innerHTML+=sessionStorage.amount+"<br/>"; } //修改 function update_click() { //如果不存在就添加,如果存在就修改 sessionStorage.setItem("name","iPhone 8 plus手机"); //修改办法2 sessionStorage["price"]=899.5; //修改办法3 sessionStorage.amount=100; } //删除 function delete_click() { //根据键删除 //sessionStorage.removeItem("price"); //删除所有 sessionStorage.clear(); } </script> </body> </html>
运行结果:
可以实现在页面间传值,比如可以临时存储用户信息。
3.2、Web本地存储事件监听
当程序修改localStorage与sessionStorage时将触发全局事件。
当setItem(),removeItem()或者clear() 方法被调用,并且数据真的发生了改变时,就会触发storage事件,如果需要进行监听数据处理,通过以下方法:
window.addEventListener(event,handleEvent, capture)
event:设置成storage
handleEvent:事件处理函数
capture:事件处理顺序,一般设置成false,表示采用冒泡方式处理
handleEvent处理事件的函数会接收到一个StorageEvent对象,该对象有以下属性:
key:被修改的键。
oldValue:修改前的值(如果是增加新的键值,则该属性为null)
newValue:修改后的值(如果是删除键值,则该属性为null)
url/uri:触发当前存储事件的页面的url
注意:storage改变的时候,触发这个事件会调用所有同域下其他窗口的storage事件,不过它本身触发storage即当前窗口是不会触发这个事件的(当然ie这个特例除外,它包含自己本事也会触发storage事件)
修改d02页面,监听值的变化。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>获得localStorage的值</title> </head> <body> <script type="text/javascript"> console.log(localStorage.price); window.addEventListener("storage",function(obj){ alert(obj.oldValue+","+obj.newValue+","+obj.url); },true); </script> </body> </html>
运行结果如下:
3.3、cookie、sessionStorage、localStorage比较
四、Web SQL Database
Web SQL Database 引入了一套使用 SQL 来操纵客户端数据库(client-side database)的 API,这些 API 是异步的(asynchronous),规范中所使用的 SQL 语言为 SQLite。Web SQL Database API 实际上未包含在 HTML 5 规范之中,它是一个独立的规范,它引入了一套使用 SQL 操作客户端数据库的 API,这些 API 有同步的,也有异步的, 同步版本的 API 只在工作线程(Worker Threads)上有用,由于并不是所有的浏览器都支持工作线程,一般情况下,都会使用异步 API。兼容情况如下:
Web SQL Database可以让开发人员使用SQL语句操作客户端浏览器中嵌入的SQLite数据库 ,给开发人员提供了方便。对于简单的数据,使用sessionStorage和localStorage能够很好地完成存取,但是对于处理复杂的关系型数据,它就力不从心了。这也是 HTML 5 的“Web SQLDatabase”API 接口的应用所在。我把它理解成一个Html5环境下可以用Js执行CRUD的Web数据库
三个核心方法
openDatabase:这个方法使用现有数据库或创建新数据库创建数据库对象。
transaction:这个方法允许我们根据情况控制事务提交或回滚。
executeSql:这个方法用于执行真实的SQL查询。
4.1、创建数据库
使用openDatabase创建或打开数据库,如果存在就打开,如果不存在就创建,语法如下:
openDatabase(a,b,c,d,e);
a).数据库名称。
b).版本号 目前为1.0
c).对数据库的描述
d).设置数据的大小,以Byte为单位
e).回调函数(可省略)
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Web SQL Database</title> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> </head> <body> <h2>Web SQL Database</h2> <h2 id="msg"></h2> <script src="js/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> //数据库 var db; //创建名称为products,版本为1.0,描述为产品数据库,3M大小的数据库 db=openDatabase("products",1.0,"产品数据库",1024*1024*3,function(){ log("创建或打开数据库完成"); }); //显示消息 function log(info){ $("#msg")[0].innerHTML+=info+"<br/>"; } </script> </body> </html>
运行结果:
4.2、创建表
执行所有的SQL语句都将使用到transaction、executeSql两个方法,基本语法格式如下:
数据库对象.transaction(function(tx) { tx.executeSql( "要执行的sql", [参数], function(tx, result) { alert('成功时的回调方法'); }, function(tx, error) { alert('失败时的回调方法' + error.message); }); });
页面脚本如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Web SQL Database</title> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> </head> <body> <h2>Web SQL Database</h2> <div> <button onclick="createTable()">创建表</button> </div> <h2 id="msg"></h2> <script src="js/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> //创建或打开名称为products,版本为1.0,描述为产品数据库,3M大小的数据库 var db = openDatabase("products", 1.0, "产品数据库", 1024 * 1024 * 3, function() { log("创建数据库完成"); }); //创建表 function createTable() { db.transaction(function(tx) { tx.executeSql( "create table if not exists goods(id integer primary key autoincrement,name text not null,price double)", [], function(tx, result) { log('创建表成功'); }, function(tx, error) { log('创建表失败' + error.message); }); }); } //显示消息 function log(info) { $("#msg")[0].innerHTML += info + "<br/>"; } </script> </body> </html>
运行结果:
当创建成功时,可以发现在出现了两个表,其中名为sqlite_sequence为自动增长用的序列。
4.3、添加数据
页面脚本如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Web SQL Database</title> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> </head> <body> <h2>Web SQL Database</h2> <div> <button onclick="createTable()">创建表</button> <fieldset> <legend>商品信息</legend> <p> <label for="name">名称:</label> <input type="text" id="name" value="" /> </p> <p> <label for="price">价格:</label> <input type="text" id="price" value="" /> </p> <p> <button onclick="insert()">添加</button> </p> </fieldset> </div> <h2 id="msg"></h2> <script src="js/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> //创建名称为products,版本为1.0,描述为产品数据库,3M大小的数据库 var db = openDatabase("products", 1.0, "产品数据库", 1024 * 1024 * 3, function() { log("创建或打开数据库完成"); }); //创建表 function createTable() { db.transaction(function(tx) { tx.executeSql( "create table if not exists goods(id integer primary key autoincrement,name text not null,price double)", [], function(tx, result) { log('创建表成功'); }, function(tx, error) { log('创建表失败' + error.message); }); }); } //插入数据 function insert() { db.transaction(function(tx) { tx.executeSql( "insert into goods(name,price) values(?,?)", [$("#name").val(),$("#price").val()], function(tx, result) { log('添加数据成功'); }, function(tx, error) { log('添加数据失败' + error.message); }); }); } //显示消息 function log(info) { $("#msg")[0].innerHTML += info + "<br/>"; } </script> </body> </html>
运行结果:
4.4、展示数据
页面脚本如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Web SQL Database</title> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> </head> <body> <h2>Web SQL Database</h2> <div> <button onclick="createTable()">创建表</button> <table border="1" width="80%" id="tabGoods"> <tr><th>编号</th><th>名称</th><th>价格</th><th>删除</th></tr> </table> <fieldset> <legend>商品信息</legend> <p> <label for="name">名称:</label> <input type="text" id="name" value="" /> </p> <p> <label for="price">价格:</label> <input type="text" id="price" value="" /> </p> <p> <button onclick="insert()">添加</button> </p> </fieldset> </div> <h2 id="msg"></h2> <script src="js/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> //创建名称为products,版本为1.0,描述为产品数据库,3M大小的数据库 var db = openDatabase("products", 1.0, "产品数据库", 1024 * 1024 * 3, function() { log("创建或打开数据库完成"); }); //展示,加载数据 function select() { //将表格中tr索引大于0的元素删除 $("#tabGoods tr:gt(0)").remove(); db.transaction(function(tx) { tx.executeSql( "select id,name,price from goods", [], function(tx, result) { for (var i=0;i<result.rows.length;i++) { var tr=$("<tr/>"); $("<td/>").text(result.rows.item(i)["id"]).appendTo(tr); $("<td/>").text(result.rows.item(i)["name"]).appendTo(tr); $("<td/>").text(result.rows.item(i)["price"]).appendTo(tr); var del=$("<a href='#' onclick='del("+result.rows.item(i)["id"]+")' >删除</a>") $("<td/>").append(del).appendTo(tr); tr.appendTo("#tabGoods"); } }, function(tx, error) { log('创建表失败' + error.message); }); }); } select(); //创建表 function createTable() { db.transaction(function(tx) { tx.executeSql( "create table if not exists goods(id integer primary key autoincrement,name text not null,price double)", [], function(tx, result) { log('创建表成功'); }, function(tx, error) { log('创建表失败' + error.message); }); }); } //插入数据 function insert() { db.transaction(function(tx) { tx.executeSql( "insert into goods(name,price) values(?,?)", [$("#name").val(),$("#price").val()], function(tx, result) { log('添加数据成功'); select(); }, function(tx, error) { log('添加数据失败' + error.message); }); }); } //显示消息 function log(info) { $("#msg")[0].innerHTML += info + "<br/>"; } </script> </body> </html>
运行结果如下:
4.5、编辑数据
页面脚本如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Web SQL Database</title> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> </head> <body> <h2>Web SQL Database</h2> <div> <button onclick="createTable()">创建表</button> <table border="1" width="80%" id="tabGoods"> <tr> <th>编号</th> <th>名称</th> <th>价格</th> <th>删除</th> </tr> </table> <fieldset> <legend>商品信息</legend> <p> <label for="name">名称:</label> <input type="text" id="name" value="" /> </p> <p> <label for="price">价格:</label> <input type="text" id="price" value="" /> </p> <p> <input type="hidden" id="goodsId" /> <button onclick="insert()">添加</button> <button onclick="update()">更新</button> </p> </fieldset> </div> <h2 id="msg"></h2> <script src="js/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> //创建名称为products,版本为1.0,描述为产品数据库,3M大小的数据库 var db = openDatabase("products", 1.0, "产品数据库", 1024 * 1024 * 3, function() { log("创建或打开数据库完成"); }); //展示,加载数据 function select() { //将表格中tr索引大于0的元素删除 $("#tabGoods tr:gt(0)").remove(); db.transaction(function(tx) { tx.executeSql( "select id,name,price from goods", [], function(tx, result) { for(var i = 0; i < result.rows.length; i++) { var tr = $("<tr/>"); $("<td/>").text(result.rows.item(i)["id"]).appendTo(tr); $("<td/>").text(result.rows.item(i)["name"]).appendTo(tr); $("<td/>").text(result.rows.item(i)["price"]).appendTo(tr); var del = $("<a href='#' onclick='del(" + result.rows.item(i)["id"] + ",this)' >删除 | </a>") var edit = $("<a href='#' onclick='edit(" + result.rows.item(i)["id"] + ",this)' >修改</a>") $("<td/>").append(del).append(edit).appendTo(tr); tr.appendTo("#tabGoods"); } }, function(tx, error) { log('创建表失败' + error.message); }); }); } select(); //创建表 function createTable() { db.transaction(function(tx) { tx.executeSql( "create table if not exists goods(id integer primary key autoincrement,name text not null,price double)", [], function(tx, result) { log('创建表成功'); }, function(tx, error) { log('创建表失败' + error.message); }); }); } //插入数据 function insert() { db.transaction(function(tx) { tx.executeSql( "insert into goods(name,price) values(?,?)", [$("#name").val(), $("#price").val()], function(tx, result) { log('添加数据成功'); select(); }, function(tx, error) { log('添加数据失败' + error.message); }); }); } //删除 function del(id, link) { db.transaction(function(tx) { tx.executeSql( "delete from goods where id=?", [id], function(tx, result) { log('删除成功'); //查找a标签最近的一个tr父元素,移除 $(link).closest("tr").remove(); }, function(tx, error) { log('删除失败' + error.message); }); }); } //编辑 function edit(id) { db.transaction(function(tx) { tx.executeSql( "select id,name,price from goods where id=?", [id], function(tx, result) { $("#name").val(result.rows.item(0)["name"]); $("#price").val(result.rows.item(0)["price"]); $("#goodsId").val(result.rows.item(0)["id"]); log("修改后请保存"); }, function(tx, error) { log('编辑失败' + error.message); }); }); } //更新 function update() { if($("#goodsId").val()) { db.transaction(function(tx) { tx.executeSql( "update goods set name=?,price=? where id=?", [$("#name").val(), $("#price").val(), $("#goodsId").val()], function(tx, result) { log('更新成功'); select(); $("#goodsId").val(""); }, function(tx, error) { log('更新失败' + error.message); }); }); } else { log("请选择要更新的记录 "); } } //显示消息 function log(info) { $("#msg")[0].innerHTML += info + "<br/>"; } </script> </body> </html>
运行结果如下:
4.6、删除数据
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Web SQL Database</title> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> </head> <body> <h2>Web SQL Database</h2> <div> <button onclick="createTable()">创建表</button> <table border="1" width="80%" id="tabGoods"> <tr><th>编号</th><th>名称</th><th>价格</th><th>删除</th></tr> </table> <fieldset> <legend>商品信息</legend> <p> <label for="name">名称:</label> <input type="text" id="name" value="" /> </p> <p> <label for="price">价格:</label> <input type="text" id="price" value="" /> </p> <p> <button onclick="insert()">添加</button> </p> </fieldset> </div> <h2 id="msg"></h2> <script src="js/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> //创建名称为products,版本为1.0,描述为产品数据库,3M大小的数据库 var db = openDatabase("products", 1.0, "产品数据库", 1024 * 1024 * 3, function() { log("创建或打开数据库完成"); }); //展示,加载数据 function select() { //将表格中tr索引大于0的元素删除 $("#tabGoods tr:gt(0)").remove(); db.transaction(function(tx) { tx.executeSql( "select id,name,price from goods", [], function(tx, result) { for (var i=0;i<result.rows.length;i++) { var tr=$("<tr/>"); $("<td/>").text(result.rows.item(i)["id"]).appendTo(tr); $("<td/>").text(result.rows.item(i)["name"]).appendTo(tr); $("<td/>").text(result.rows.item(i)["price"]).appendTo(tr); var del=$("<a href='#' onclick='del("+result.rows.item(i)["id"]+",this)' >删除</a>") $("<td/>").append(del).appendTo(tr); tr.appendTo("#tabGoods"); } }, function(tx, error) { log('创建表失败' + error.message); }); }); } select(); //创建表 function createTable() { db.transaction(function(tx) { tx.executeSql( "create table if not exists goods(id integer primary key autoincrement,name text not null,price double)", [], function(tx, result) { log('创建表成功'); }, function(tx, error) { log('创建表失败' + error.message); }); }); } //插入数据 function insert() { db.transaction(function(tx) { tx.executeSql( "insert into goods(name,price) values(?,?)", [$("#name").val(),$("#price").val()], function(tx, result) { log('添加数据成功'); select(); }, function(tx, error) { log('添加数据失败' + error.message); }); }); } //删除 function del(id,link) { db.transaction(function(tx) { tx.executeSql( "delete from goods where id=?", [id], function(tx, result) { log('删除成功'); //查找a标签最近的一个tr父元素,移除 $(link).closest("tr").remove(); }, function(tx, error) { log('删除失败' + error.message); }); }); } //显示消息 function log(info) { $("#msg")[0].innerHTML += info + "<br/>"; } </script> </body> </html>
运行结果:
4.7、删除表
删除表
//创建表 function dropTable() { db.transaction(function(tx) { tx.executeSql( "drop table IF EXISTS goods", [], function(tx, result) { log('删除表成功'); }, function(tx, error) { log('删除表失败' + error.message); }); }); }
运行结果:
4.8、数据库位置
D:\Users\Administrator\AppData\Local\Google\Chrome\User Data\Default\databases
4.9、封装JavaScript
前面的示例中javascript方法都直接暴露在window下,有可能与别的js冲突,可以进行简单封装。
简单对象封装示例:
var ticker={ n:0, add:function() { this.n++; }, show:function() { alert(this.n); } } ticker.add(); ticker.add(); ticker.show();
运行结果:2
第一次封装后的代码,在整个window对象中只暴露dbApp对象,代码如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Web SQL Database</title> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> </head> <body> <h2>Web SQL Database</h2> <div> <button id="btnCreateTable">创建表</button> <button id="btnDropTable">删除表</button> <table border="1" width="80%" id="tabGoods"> <tr> <th>编号</th> <th>名称</th> <th>价格</th> <th>删除</th> </tr> </table> <fieldset> <legend>商品信息</legend> <p> <label for="name">名称:</label> <input type="text" id="name" value="" /> </p> <p> <label for="price">价格:</label> <input type="text" id="price" value="" /> </p> <p> <input type="hidden" id="goodsId" /> <button id="btnInsert">添加</button> <button id="btnUpdate">更新</button> </p> </fieldset> </div> <h2 id="msg"></h2> <script src="js/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> //定义当前应用的对象 var dbApp={ //打开数据库 openDb:function() { //创建名称为products,版本为1.0,描述为产品数据库,3M大小的数据库 this.db = openDatabase("products", 1.0, "产品数据库", 1024 * 1024 * 3, function() { this.log("创建或打开数据库完成"); }); }, //初始化 init:function() { //打开或创建数据库 this.openDb(); //绑定事件 this.bindEvent(); //展示数据 this.select(); this.log("初始化完成"); }, //绑定事件 bindEvent:function() { //添加事件 $("#btnInsert").click(this.insert); $("#btnUpdate").click(this.update); $("#btnCreateTable").click(this.createTable); $("#btnDropTable").click(this.dropTable); }, //显示消息 log:function(info) { $("#msg")[0].innerHTML += info + "<br/>"; }, //创建表 createTable:function() { this.db.transaction(function(tx) { tx.executeSql( "create table IF not EXISTS goods(id integer primary key autoincrement,name text not null,price double)", [], function(tx, result) { this.log('创建表成功'); }, function(tx, error) { this.log('创建表失败' + error.message); }); }); }, //删除表 dropTable:function() { this.db.transaction(function(tx) { tx.executeSql( "drop table IF EXISTS goods", [], function(tx, result) { this.log('删除表成功'); }, function(tx, error) { this.log('删除表失败' + error.message); }); }); }, //展示,加载数据 select:function() { //将表格中tr索引大于0的元素删除 $("#tabGoods tr:gt(0)").remove(); this.db.transaction(function(tx) { tx.executeSql( "select id,name,price from goods", [], function(tx, result) { for(var i = 0; i < result.rows.length; i++) { var tr = $("<tr/>"); $("<td/>").text(result.rows.item(i)["id"]).appendTo(tr); $("<td/>").text(result.rows.item(i)["name"]).appendTo(tr); $("<td/>").text(result.rows.item(i)["price"]).appendTo(tr); var del = $("<a href='#' onclick='dbApp.del(" + result.rows.item(i)["id"] + ",this)' >删除 | </a>") var edit = $("<a href='#' onclick='dbApp.edit(" + result.rows.item(i)["id"] + ",this)' >修改</a>") $("<td/>").append(del).append(edit).appendTo(tr); tr.appendTo("#tabGoods"); } }, function(tx, error) { this.log('创建表失败' + error.message); }); }); }, //插入数据 insert:function() { //如果insert方法被绑定为事件,则this表示事件发生的对象 dbApp.db.transaction(function(tx) { tx.executeSql( "insert into goods(name,price) values(?,?)", [$("#name").val(), $("#price").val()], function(tx, result) { dbApp.log('添加数据成功'); //刷新 dbApp.select(); }, function(tx, error) { dbApp.log('添加数据失败' + error.message); }); }); }, //删除 del:function(id, link) { dbApp.db.transaction(function(tx) { tx.executeSql( "delete from goods where id=?", [id], function(tx, result) { dbApp.log('删除成功'); //查找a标签最近的一个tr父元素,移除 $(link).closest("tr").remove(); }, function(tx, error) { dbApp.log('删除失败' + error.message); }); }); }, //编辑 edit:function(id) { dbApp.db.transaction(function(tx) { tx.executeSql( "select id,name,price from goods where id=?", [id], function(tx, result) { $("#name").val(result.rows.item(0)["name"]); $("#price").val(result.rows.item(0)["price"]); $("#goodsId").val(result.rows.item(0)["id"]); dbApp.log("修改后请保存"); }, function(tx, error) { dbApp.log('编辑失败' + error.message); }); }); }, //更新 update:function() { if($("#goodsId").val()) { dbApp.db.transaction(function(tx) { tx.executeSql( "update goods set name=?,price=? where id=?", [$("#name").val(), $("#price").val(), $("#goodsId").val()], function(tx, result) { dbApp.log('更新成功'); dbApp.select(); $("#goodsId").val(""); }, function(tx, error) { dbApp.log('更新失败' + error.message); }); }); } else { dbApp.log("请选择要更新的记录 "); } } }; dbApp.init(); </script> </body> </html>
运行结果:
从上面的代码可以发现操作数据库,执行sql的方法存在大量的冗余,可以优化,优化后的代码如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Web SQL Database</title> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> </head> <body> <h2>Web SQL Database</h2> <div> <button id="btnCreateTable">创建表</button> <button id="btnDropTable">删除表</button> <table border="1" width="80%" id="tabGoods"> <tr> <th>编号</th> <th>名称</th> <th>价格</th> <th>删除</th> </tr> </table> <fieldset> <legend>商品信息</legend> <p> <label for="name">名称:</label> <input type="text" id="name" value="" /> </p> <p> <label for="price">价格:</label> <input type="text" id="price" value="" /> </p> <p> <input type="hidden" id="goodsId" /> <button id="btnInsert">添加</button> <button id="btnUpdate">更新</button> </p> </fieldset> </div> <h2 id="msg"></h2> <script src="js/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> //定义当前应用的对象 var dbApp={ //打开数据库 openDb:function() { //创建名称为products,版本为1.0,描述为产品数据库,3M大小的数据库 this.db = openDatabase("products", 1.0, "产品数据库", 1024 * 1024 * 3, function() { this.log("创建或打开数据库完成"); }); }, //初始化 init:function() { //打开或创建数据库 this.openDb(); //绑定事件 this.bindEvent(); //展示数据 this.select(); this.log("初始化完成"); }, //绑定事件 bindEvent:function() { //添加事件 $("#btnInsert").click(this.insert); $("#btnUpdate").click(this.update); $("#btnCreateTable").click(this.createTable); $("#btnDropTable").click(this.dropTable); }, //显示消息 log:function(info) { $("#msg")[0].innerHTML += info + "<br/>"; }, //执行sql的通用方法 result.rowsAffected 影响行数 //callback执行成功时的回调方法 exeSql:function(sql,title,param,callback) { title=title||"操作"; this.db.transaction(function(tx) { tx.executeSql( sql, param||[], function(tx, result) { dbApp.log(title+'成功'); if(callback){ //如果有参数 callback(result); } }, function(tx, error) { dbApp.log(title+'失败' + error.message); }); }); }, //创建表 createTable:function() { dbApp.exeSql("create table IF not EXISTS goods(id integer primary key autoincrement,name text not null,price double)","创建表"); }, //删除表 dropTable:function() { dbApp.exeSql("drop table IF EXISTS goods","删除表"); }, //展示,加载数据 select:function() { dbApp.exeSql("select id,name,price from goods","查询",[],function(result) { //将表格中tr索引大于0的元素删除 $("#tabGoods tr:gt(0)").remove(); for(var i = 0; i < result.rows.length; i++) { var tr = $("<tr/>"); $("<td/>").text(result.rows.item(i)["id"]).appendTo(tr); $("<td/>").text(result.rows.item(i)["name"]).appendTo(tr); $("<td/>").text(result.rows.item(i)["price"]).appendTo(tr); var del = $("<a href='#' onclick='dbApp.del(" + result.rows.item(i)["id"] + ",this)' >删除 | </a>") var edit = $("<a href='#' onclick='dbApp.edit(" + result.rows.item(i)["id"] + ",this)' >修改</a>") $("<td/>").append(del).append(edit).appendTo(tr); tr.appendTo("#tabGoods"); } }); }, //插入数据 insert:function() { //如果insert方法被绑定为事件,则this表示事件发生的对象 dbApp.exeSql("insert into goods(name,price) values(?,?)","添加",[$("#name").val(), $("#price").val()],function(){ dbApp.select(); }); }, //删除 del:function(id, link) { dbApp.exeSql("delete from goods where id=?","删除",[id],function(result){ //查找a标签最近的一个tr父元素,移除 $(link).closest("tr").remove(); }); }, //编辑 edit:function(id) { dbApp.exeSql("select id,name,price from goods where id=?","编辑",[id],function(result) { $("#name").val(result.rows.item(0)["name"]); $("#price").val(result.rows.item(0)["price"]); $("#goodsId").val(result.rows.item(0)["id"]); dbApp.log("修改后请保存"); }); }, //更新 update:function() { if($("#goodsId").val()) { dbApp.exeSql("update goods set name=?,price=? where id=?","更新",[$("#name").val(), $("#price").val(), $("#goodsId").val()],function(result) { dbApp.select(); $("#goodsId").val(""); }); } else { dbApp.log("请选择要更新的记录 "); } } }; dbApp.init(); </script> </body> </html>
运行结果:
4.10、美化页面
在原页面的基础上增加css样式,添加样式后的页面脚本如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Web SQL Database</title> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> <style type="text/css"> * { margin: 0; padding: 0; font-family: "microsoft yahei"; } #container{ padding: 10px; font-size: 14px; } #container a{ color: #fff; text-decoration: none; margin-right: 5px; } #container a:hover{ color:orangered; } button,a{ border: 0; height: 22px; line-height: 22px; border-radius: 3px; padding:0 10px; background: dodgerblue; color: white; } button:hover{ background: orangered; } #container h2{ height: 60px; } html #tabGoods{ width:100%; margin: 15px 0; border: 2px solid #0062CC; } #tabGoods,#tabGoods td,#tabGoods th { border: 1px solid #0062CC; border-collapse: collapse; } #tabGoods td,#tabGoods th{ padding: 5px 0 5px 5px; } #fieldsetForm{ width: 400px; padding: 10px; border-radius: 10px; border: 2px solid #0062CC; } #fieldsetForm p{ padding: 10px; } #msg{ font-size: 16px; font-weight: normal; height: 100px; overflow: auto; margin-top: 10px; } </style> </head> <body> <div id="container"> <h2>Web SQL Database</h2> <button id="btnCreateTable">创建表</button> <button id="btnDropTable">删除表</button> <table id="tabGoods"> <tr> <th>编号</th> <th>名称</th> <th>价格</th> <th>删除</th> </tr> </table> <fieldset id="fieldsetForm"> <legend>商品信息</legend> <p> <label for="name">名称:</label> <input type="text" id="name" value="" /> </p> <p> <label for="price">价格:</label> <input type="text" id="price" value="" /> </p> <p> <input type="hidden" id="goodsId" /> <button id="btnInsert">添加</button> <button id="btnUpdate">更新</button> </p> </fieldset> <h2 id="msg"></h2> </div> <script src="js/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript"> //定义当前应用的对象 var dbApp = { //打开数据库 openDb: function() { //创建名称为products,版本为1.0,描述为产品数据库,3M大小的数据库 this.db = openDatabase("products", 1.0, "产品数据库", 1024 * 1024 * 3, function() { this.log("创建或打开数据库完成"); }); }, //初始化 init: function() { //打开或创建数据库 this.openDb(); //绑定事件 this.bindEvent(); //展示数据 this.select(); this.log("初始化完成"); }, //绑定事件 bindEvent: function() { //添加事件 $("#btnInsert").click(this.insert); $("#btnUpdate").click(this.update); $("#btnCreateTable").click(this.createTable); $("#btnDropTable").click(this.dropTable); }, //显示消息 log: function(info) { $("#msg")[0].innerHTML += info + "<br/>"; }, //执行sql的通用方法 result.rowsAffected 影响行数 //callback执行成功时的回调方法 exeSql: function(sql, title, param, callback) { title = title || "操作"; this.db.transaction(function(tx) { tx.executeSql( sql, param || [], function(tx, result) { dbApp.log(title + '成功'); if(callback) { //如果有参数 callback(result); } }, function(tx, error) { dbApp.log(title + '失败' + error.message); }); }); }, //创建表 createTable: function() { dbApp.exeSql("create table IF not EXISTS goods(id integer primary key autoincrement,name text not null,price double)", "创建表"); }, //删除表 dropTable: function() { dbApp.exeSql("drop table IF EXISTS goods", "删除表"); }, //展示,加载数据 select: function() { dbApp.exeSql("select id,name,price from goods", "查询", [], function(result) { //将表格中tr索引大于0的元素删除 $("#tabGoods tr:gt(0)").remove(); for(var i = 0; i < result.rows.length; i++) { var tr = $("<tr/>"); $("<td/>").text(result.rows.item(i)["id"]).appendTo(tr); $("<td/>").text(result.rows.item(i)["name"]).appendTo(tr); $("<td/>").text(result.rows.item(i)["price"]).appendTo(tr); var del = $("<a href='#' onclick='dbApp.del(" + result.rows.item(i)["id"] + ",this)' >删除</a> ") var edit = $("<a href='#' onclick='dbApp.edit(" + result.rows.item(i)["id"] + ",this)' >修改</a>") $("<td/>").append(del).append(edit).appendTo(tr); tr.appendTo("#tabGoods"); } }); }, //插入数据 insert: function() { //如果insert方法被绑定为事件,则this表示事件发生的对象 dbApp.exeSql("insert into goods(name,price) values(?,?)", "添加", [$("#name").val(), $("#price").val()], function() { dbApp.select(); }); }, //删除 del: function(id, link) { dbApp.exeSql("delete from goods where id=?", "删除", [id], function(result) { //查找a标签最近的一个tr父元素,移除 $(link).closest("tr").remove(); }); }, //编辑 edit: function(id) { dbApp.exeSql("select id,name,price from goods where id=?", "编辑", [id], function(result) { $("#name").val(result.rows.item(0)["name"]); $("#price").val(result.rows.item(0)["price"]); $("#goodsId").val(result.rows.item(0)["id"]); dbApp.log("修改后请保存"); }); }, //更新 update: function() { if($("#goodsId").val()) { dbApp.exeSql("update goods set name=?,price=? where id=?", "更新", [$("#name").val(), $("#price").val(), $("#goodsId").val()], function(result) { dbApp.select(); $("#goodsId").val(""); }); } else { dbApp.log("请选择要更新的记录 "); } } }; dbApp.init(); </script> </body> </html>
运行结果:
五、移动端打包与运行
5.1、在手机端直接访问Web站点
将手机与电脑连接到同一个网段,比如可以使用wifi
查看本机ip地址,有时需要将本地连接禁用,查看ip地址的指令是ipconfig
在手机端使用浏览器查看结果如下:
5.2、打包成app安装运行
这里使用HBuilder打包成apk的安装包,安装打包结果如下:
5.3、套用移动端UI框架
这里使用HBuilder内置的MUI为例,新增d06.html,页面脚本如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>淘水果</title> <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <!--标准mui.css--> <link rel="stylesheet" href="css/mui.min.css"> <!--App自定义的css--> <link rel="stylesheet" type="text/css" href="css/app.css" /> <style> .title { margin: 20px 15px 10px; color: #6d6d72; font-size: 15px; } .oa-contact-cell.mui-table .mui-table-cell { padding: 11px 0; vertical-align: middle; } .oa-contact-cell { position: relative; margin: -11px 0; } .oa-contact-avatar { width: 75px; } .oa-contact-avatar img { border-radius: 50%; } .oa-contact-content { width: 100%; } .oa-contact-name { margin-right: 20px; } .oa-contact-name, oa-contact-position { float: left; } </style> </head> <body> <header class="mui-bar mui-bar-nav"> <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a> <h1 class="mui-title">淘水果</h1> </header> <nav class="mui-bar mui-bar-tab"> <a class="mui-tab-item mui-active" href="#tabbar"> <span class="mui-icon mui-icon-home"></span> <span class="mui-tab-label">畅销水果</span> </a> <a class="mui-tab-item" href="#tabbar-with-chat"> <span class="mui-icon mui-icon-email"><span class="mui-badge">9</span></span> <span class="mui-tab-label">新货上架</span> </a> <a class="mui-tab-item" href="#tabbar-with-contact"> <span class="mui-icon mui-icon-contact"></span> <span class="mui-tab-label">收款</span> </a> <a class="mui-tab-item" href="#tabbar-with-map"> <span class="mui-icon mui-icon-gear"></span> <span class="mui-tab-label">发货</span> </a> </nav> <div class="mui-content"> <div id="tabbar" class="mui-control-content mui-active"> <div id="slider" class="mui-slider"> <div class="mui-slider-group mui-slider-lhttp://127.0.0.1:8020/HTML5_2_1/d06.html#oop"> <!-- 额外增加的一个节点(循环轮播:第一个节点是最后一张轮播) --> <div class="mui-slider-item mui-slider-item-duplicate"> <a href="#"> <img src="images/yuantiao.jpg"> </a> </div> <!-- 第一张 --> <div class="mui-slider-item"> <a href="#"> <img src="images/shuijiao.jpg"> </a> </div> <!-- 第二张 --> <div class="mui-slider-item"> <a href="#"> <img src="images/muwu.jpg"> </a> </div> <!-- 第三张 --> <div class="mui-slider-item"> <a href="#"> <img src="images/cbd.jpg"> </a> </div> <!-- 第四张 --> <div class="mui-slider-item"> <a href="#"> <img src="images/yuantiao.jpg"> </a> </div> <!-- 额外增加的一个节点(循环轮播:最后一个节点是第一张轮播) --> <div class="mui-slider-item mui-slider-item-duplicate"> <a href="#"> <img src="images/shuijiao.jpg"> </a> </div> </div> <div class="mui-slider-indicator"> <div class="mui-indicator mui-active"></div> <div class="mui-indicator"></div> <div class="mui-indicator"></div> <div class="mui-indicator"></div> </div> </div> <ul class="mui-table-view mui-table-view-chevron" id="goodsList"> </ul> </div> <div id="tabbar-with-chat" class="mui-control-content"> <p> <label for="name">名称:</label> <input type="text" id="name" value="" /> </p> <p> <label for="price">价格:</label> <input type="text" id="price" value="" /> </p> <p> <input type="hidden" id="goodsId" /> <button id="btnInsert">添加</button> <button id="btnUpdate">更新</button> </p> </div> <div id="tabbar-with-contact" class="mui-control-content"> <div class="title">这是div模式选项卡中的第3个子页面,该页面展示一个通讯录示例.</div> <ul class="mui-table-view mui-table-view-striped mui-table-view-condensed"> <li class="mui-table-view-cell"> <div class="mui-slider-cell"> <div class="oa-contact-cell mui-table"> <div class="oa-contact-avatar mui-table-cell"> <img src="images/60x60.gif" /> </div> <div class="oa-contact-content mui-table-cell"> <div class="mui-clearfix"> <h4 class="oa-contact-name">叶文洁</h4> <span class="oa-contact-position mui-h6">董事长</span> </div> <p class="oa-contact-email mui-h6"> yewenjie@sina.com </p> </div> </div> </div> </li> <li class="mui-table-view-cell"> <div class="mui-slider-cell"> <div class="oa-contact-cell mui-table"> <div class="oa-contact-avatar mui-table-cell"> <img src="images/60x60.gif" /> </div> <div class="oa-contact-content mui-table-cell"> <div class="mui-clearfix"> <h4 class="oa-contact-name">艾AA</h4> <span class="oa-contact-position mui-h6">总经理</span> </div> <p class="oa-contact-email mui-h6"> aaa@163.com </p> </div> </div> </div> </li> <li class="mui-table-view-cell"> <div class="mui-slider-cell"> <div class="oa-contact-cell mui-table"> <div class="oa-contact-avatar mui-table-cell"> <img src="images/60x60.gif" /> </div> <div class="oa-contact-content mui-table-cell"> <div class="mui-clearfix"> <h4 class="oa-contact-name">罗辑</h4> <span class="oa-contact-position mui-h6">员工</span> </div> <p class="oa-contact-email mui-h6"> luoji@126.com </p> </div> </div> </div> </li> <li class="mui-table-view-cell"> <div class="mui-slider-cell"> <div class="oa-contact-cell mui-table"> <div class="oa-contact-avatar mui-table-cell"> <img src="images/60x60.gif" /> </div> <div class="oa-contact-content mui-table-cell"> <div class="mui-clearfix"> <h4 class="oa-contact-name">云天明</h4> <span class="oa-contact-position mui-h6">员工</span> </div> <p class="oa-contact-email mui-h6"> ytm@163.com </p> </div> </div> </div> </li> <li class="mui-table-view-cell"> <div class="mui-slider-cell"> <div class="oa-contact-cell mui-table"> <div class="oa-contact-avatar mui-table-cell"> <img src="images/60x60.gif" /> </div> <div class="oa-contact-content mui-table-cell"> <div class="mui-clearfix"> <h4 class="oa-contact-name">史强</h4> <span class="oa-contact-position mui-h6">员工</span> </div> <p class="oa-contact-email mui-h6"> shiqiang@gmail.com </p> </div> </div> </div> </li> </ul> </div> <div id="tabbar-with-map" class="mui-control-content"> <div class="title">这是div模式选项卡中的第4个子页面,该页面展示一个常见的设置示例.</div> <ul class="mui-table-view"> <li class="mui-table-view-cell"> <a class="mui-navigate-right"> 新消息通知 </a> </li> <li class="mui-table-view-cell"> <a class="mui-navigate-right"> 隐私 </a> </li> <li class="mui-table-view-cell"> <a class="mui-navigate-right"> 通用 </a> </li> </ul> <ul class="mui-table-view" style="margin-top: 25px;"> <li class="mui-table-view-cell"> <a class="mui-navigate-right"> 关于mui </a> </li> </ul> <ul class="mui-table-view" style="margin-top: 25px;"> <li class="mui-table-view-cell"> <a style="text-align: center;color: #FF3B30;"> 退出登录 </a> </li> </ul> </div> </div> </body> <script src="js/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script> <script src="js/mui.min.js"></script> <script> //定义当前应用的对象 var dbApp = { //打开数据库 openDb: function() { //创建名称为products,版本为1.0,描述为产品数据库,3M大小的数据库 this.db = openDatabase("products", 1.0, "产品数据库", 1024 * 1024 * 3, function() { this.log("创建或打开数据库完成"); }); }, //初始化 init: function() { //打开或创建数据库 this.openDb(); //绑定事件 this.bindEvent(); //展示数据 this.select(); this.log("初始化完成"); }, //绑定事件 bindEvent: function() { //添加事件 $("#btnInsert").click(this.insert); $("#btnUpdate").click(this.update); $("#btnCreateTable").click(this.createTable); $("#btnDropTable").click(this.dropTable); }, //显示消息 log: function(info) { mui.toast(info); }, //执行sql的通用方法 result.rowsAffected 影响行数 //callback执行成功时的回调方法 exeSql: function(sql, title, param, callback) { title = title || "操作"; this.db.transaction(function(tx) { tx.executeSql( sql, param || [], function(tx, result) { dbApp.log(title + '成功'); if(callback) { //如果有参数 callback(result); } }, function(tx, error) { dbApp.log(title + '失败' + error.message); }); }); }, //创建表 createTable: function() { dbApp.exeSql("create table IF not EXISTS goods(id integer primary key autoincrement,name text not null,price double)", "创建表"); }, //删除表 dropTable: function() { dbApp.exeSql("drop table IF EXISTS goods", "删除表"); }, //展示,加载数据 select: function() { dbApp.exeSql("select id,name,price from goods", "查询", [], function(result) { //将表格中tr索引大于0的元素删除 $("#goodsList li").remove(); for(var i = 0; i < result.rows.length; i++) { var tr = $("<li class='mui-table-view-cell mui-media'><a class='mui-navigate-right'><img class='mui-media-object mui-pull-left' src='images/cbd.jpg'><div class='mui-media-body'>" + result.rows.item(i)["name"] + "<p class='mui-ellipsis'>新鲜好吃的水果,仅售:" + result.rows.item(i)["price"] + "/斤</p></div></a></li>") tr.appendTo("#goodsList"); } mui.init({ swipeBack: true //启用右滑关闭功能 }); }); }, //插入数据 insert: function() { //如果insert方法被绑定为事件,则this表示事件发生的对象 dbApp.exeSql("insert into goods(name,price) values(?,?)", "添加", [$("#name").val(), $("#price").val()], function() { dbApp.select(); }); }, //删除 del: function(id, link) { dbApp.exeSql("delete from goods where id=?", "删除", [id], function(result) { //查找a标签最近的一个tr父元素,移除 $(link).closest("tr").remove(); }); }, //编辑 edit: function(id) { dbApp.exeSql("select id,name,price from goods where id=?", "编辑", [id], function(result) { $("#name").val(result.rows.item(0)["name"]); $("#price").val(result.rows.item(0)["price"]); $("#goodsId").val(result.rows.item(0)["id"]); dbApp.log("修改后请保存"); }); }, //更新 update: function() { if($("#goodsId").val()) { dbApp.exeSql("update goods set name=?,price=? where id=?", "更新", [$("#name").val(), $("#price").val(), $("#goodsId").val()], function(result) { dbApp.select(); $("#goodsId").val(""); }); } else { dbApp.log("请选择要更新的记录 "); } } }; dbApp.init(); </script> </html>
打包运行后的结果如下: