HTML5 學習總結(三)——本地存儲(localStorage、sessionStorage、WebSqlDataBase、IndexedDB)


HTML5問世以后,前端加入了一個重要的功能,便是本地存儲,本地存儲可分為4類:

Local Storage:總的存儲量有所限制,並不能提供真正的檢索API,數據的生命期比窗口或瀏覽器的生命期長,數據可被同源的每個窗口或者標簽頁共享,兼容性很好,使用最多的存儲方式。

Session Storage:只要瀏覽器窗口不關閉就會一直存在,不應該把真正有價值的東西放在里面,數據會保存到存儲它的窗口或者標簽頁關閉時,數據只在構建他們的窗口或者標簽頁可見

Indexed Database:在Indexed Database中,objectstore代替了傳統的表的概念,每個objectstore相當於一個key和value的集合,IndexedDB並不像傳統的如SQL Server那樣需要額外安裝。Indexed是存在於瀏覽器端的並且能被用戶所訪問控制。是保存不敏感用戶數據的最佳方案,也可以用於創建本地應用,NOSql。

Web SQL Database:實際上未包含在HTML5規范中。和Indexed Database都是在客戶端存儲大量結構化數據的解決方案。web sql database實現了傳統的基於sql語句的數據庫操作,而indexed database實現了nosql的存儲方式,關系數據庫。

Indexed Database通過直接執行同步或者異步的函數調用來檢索樹狀的對象存儲引擎。索引數據庫API避開了查詢字符串,它使用的底層API支持將值直接存儲在javascript對象中。存儲在數據庫中的值可以通過鍵或使用索引獲取到,並且可以使用同步或異步方式訪問API。索引數據庫也限定在同源范圍內。

一、HTML4客戶端存儲

B/S架構的應用大量的信息存儲在服務器端,客戶端通過請求響應的方式從服務器獲得數據,這樣集中存儲也會給服務器帶來相應的壓力,有些數據可以直接存儲在客戶端,傳統的Web技術中會使用Cookie,但Cookie有一些缺點,為了說明這個缺點我們先看看當提交表單時會有那些信息會被瀏覽器收集后發送到服務器。

Cookies 客戶端 獨享 4K

Session 服務端 獨享 少量

Application 服務端 共享 小量

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 的存儲方式。

Web Storage 這種用於存儲 (key, value),一般兩者都是字符串;

IndexDB 是增強型的 Web Storage,也是存儲 (key, value);

Web SQL 則是 SQLite,一個完整的關系型數據庫,可以執行 SQL。

WebSQL是SQLite在瀏覽器中的實現,所以它是一種關系型數據庫。由於W3C對其規范定義不夠理想,各家瀏覽器有各自實現,有瀏覽器兼容問題;

IndexDB是一種key-value類型的非關系數據庫(NoSQL)

1.3、客戶端操作Cookies

1.3.1、獲得操作cookies的庫

https://github.com/js-cookie/js-cookie

官方幫助說明:

A simple, lightweight JavaScript API for handling cookies

Works in all browsers
Accepts any character
Heavily tested
No dependency
Unobtrusive JSON support
Supports AMD/CommonJS
RFC 6265 compliant
Useful Wiki
Enable custom encoding/decoding
~900 bytes gzipped!
If you're viewing this at https://github.com/js-cookie/js-cookie, you're reading the documentation for the master branch. View documentation for the latest release.

Build Status Matrix (including active Pull Requests)
Selenium Test Status

Installation
Direct download
Download the script here and include it (unless you are packaging scripts somehow else):

<script src="/path/to/js.cookie.js"></script>
Or include it via jsDelivr CDN:

<script src="https://cdn.jsdelivr.net/npm/js-cookie@2/src/js.cookie.min.js"></script>
Do not include the script directly from GitHub (http://raw.github.com/...). The file is being served as text/plain and as such being blocked in Internet Explorer on Windows 7 for instance (because of the wrong MIME type). Bottom line: GitHub is not a CDN.

Package Managers
JavaScript Cookie supports npm and Bower under the name js-cookie.

NPM
  $ npm install js-cookie --save
Module Loaders
JavaScript Cookie can also be loaded as an AMD or CommonJS module.

Basic Usage
Create a cookie, valid across the entire site:

Cookies.set('name', 'value');
Create a cookie that expires 7 days from now, valid across the entire site:

Cookies.set('name', 'value', { expires: 7 });
Create an expiring cookie, valid to the path of the current page:

Cookies.set('name', 'value', { expires: 7, path: '' });
Read cookie:

Cookies.get('name'); // => 'value'
Cookies.get('nothing'); // => undefined
Read all visible cookies:

Cookies.get(); // => { name: 'value' }
Note: It is not possible to read a particular cookie by passing one of the cookie attributes (which may or may not have been used when writing the cookie in question):

Cookies.get('foo', { domain: 'sub.example.com' }); // `domain` won't have any effect...!
The cookie with the name foo will only be available on .get() if it's visible from where the code is called; the domain and/or path attribute will not have an effect when reading.

Delete cookie:

Cookies.remove('name');
Delete a cookie valid to the path of the current page:

Cookies.set('name', 'value', { path: '' });
Cookies.remove('name'); // fail!
Cookies.remove('name', { path: '' }); // removed!
IMPORTANT! When deleting a cookie, you must pass the exact same path and domain attributes that were used to set the cookie, unless you're relying on the default attributes.

Note: Removing a nonexistent cookie does not raise any exception nor return any value.

Namespace conflicts
If there is any danger of a conflict with the namespace Cookies, the noConflict method will allow you to define a new namespace and preserve the original one. This is especially useful when running the script on third party sites e.g. as part of a widget or SDK.

// Assign the js-cookie api to a different variable and restore the original "window.Cookies"
var Cookies2 = Cookies.noConflict();
Cookies2.set('name', 'value');
Note: The .noConflict method is not necessary when using AMD or CommonJS, thus it is not exposed in those environments.

JSON
js-cookie provides unobtrusive JSON storage for cookies.

When creating a cookie you can pass an Array or Object Literal instead of a string in the value. If you do so, js-cookie will store the string representation of the object according to JSON.stringify:

Cookies.set('name', { foo: 'bar' });
When reading a cookie with the default Cookies.get api, you receive the string representation stored in the cookie:

Cookies.get('name'); // => '{"foo":"bar"}'
Cookies.get(); // => { name: '{"foo":"bar"}' }
When reading a cookie with the Cookies.getJSON api, you receive the parsed representation of the string stored in the cookie according to JSON.parse:

Cookies.getJSON('name'); // => { foo: 'bar' }
Cookies.getJSON(); // => { name: { foo: 'bar' } }
Note: To support IE6-7 (and IE 8 compatibility mode) you need to include the JSON-js polyfill: https://github.com/douglascrockford/JSON-js

Encoding
This project is RFC 6265 compliant. All special characters that are not allowed in the cookie-name or cookie-value are encoded with each one's UTF-8 Hex equivalent using percent-encoding.
The only character in cookie-name or cookie-value that is allowed and still encoded is the percent % character, it is escaped in order to interpret percent input as literal.
Please note that the default encoding/decoding strategy is meant to be interoperable only between cookies that are read/written by js-cookie. To override the default encoding/decoding strategy you need to use a converter.

Cookie Attributes
Cookie attributes defaults can be set globally by setting properties of the Cookies.defaults object or individually for each call to Cookies.set(...) by passing a plain object in the last argument. Per-call attributes override the default attributes.

expires
Define when the cookie will be removed. Value can be a Number which will be interpreted as days from time of creation or a Date instance. If omitted, the cookie becomes a session cookie.

To create a cookie that expires in less than a day, you can check the FAQ on the Wiki.

Default: Cookie is removed when the user closes the browser.

Examples:

Cookies.set('name', 'value', { expires: 365 });
Cookies.get('name'); // => 'value'
Cookies.remove('name');
path
A String indicating the path where the cookie is visible.

Default: /

Examples:

Cookies.set('name', 'value', { path: '' });
Cookies.get('name'); // => 'value'
Cookies.remove('name', { path: '' });
Note regarding Internet Explorer:

Due to an obscure bug in the underlying WinINET InternetGetCookie implementation, IE’s document.cookie will not return a cookie if it was set with a path attribute containing a filename.

(From Internet Explorer Cookie Internals (FAQ))

This means one cannot set a path using window.location.pathname in case such pathname contains a filename like so: /check.html (or at least, such cookie cannot be read correctly).

In fact, you should never allow untrusted input to set the cookie attributes or you might be exposed to a XSS attack.

domain
A String indicating a valid domain where the cookie should be visible. The cookie will also be visible to all subdomains.

Default: Cookie is visible only to the domain or subdomain of the page where the cookie was created, except for Internet Explorer (see below).

Examples:

Assuming a cookie that is being created on site.com:

Cookies.set('name', 'value', { domain: 'subdomain.site.com' });
Cookies.get('name'); // => undefined (need to read at 'subdomain.site.com')
Note regarding Internet Explorer default behavior:

Q3: If I don’t specify a DOMAIN attribute (for) a cookie, IE sends it to all nested subdomains anyway?
A: Yes, a cookie set on example.com will be sent to sub2.sub1.example.com.
Internet Explorer differs from other browsers in this regard.

(From Internet Explorer Cookie Internals (FAQ))

This means that if you omit the domain attribute, it will be visible for a subdomain in IE.

secure
Either true or false, indicating if the cookie transmission requires a secure protocol (https).

Default: No secure protocol requirement.

Examples:

Cookies.set('name', 'value', { secure: true });
Cookies.get('name'); // => 'value'
Cookies.remove('name');
Converters
Read
Create a new instance of the api that overrides the default decoding implementation.
All get methods that rely in a proper decoding to work, such as Cookies.get() and Cookies.get('name'), will run the converter first for each cookie.
The returning String will be used as the cookie value.

Example from reading one of the cookies that can only be decoded using the escape function:

document.cookie = 'escaped=%u5317';
document.cookie = 'default=%E5%8C%97';
var cookies = Cookies.withConverter(function (value, name) {
    if ( name === 'escaped' ) {
        return unescape(value);
    }
});
cookies.get('escaped'); // 北
cookies.get('default'); // 北
cookies.get(); // { escaped: '北', default: '北' }
Write
Create a new instance of the api that overrides the default encoding implementation:

Cookies.withConverter({
    read: function (value, name) {
        // Read converter
    },
    write: function (value, name) {
        // Write converter
    }
});
Server-side integration
Check out the Servers Docs

Contributing
Check out the Contributing Guidelines

Security
For vulnerability reports, send an e-mail to jscookieproject at gmail dot com

Manual release steps
Increment the "version" attribute of package.json
Increment the version number in the src/js.cookie.js file
If major bump, update jsDelivr CDN major version link on README
Commit with the message "Release version x.x.x"
Create version tag in git
Create a github release and upload the minified file
Change the latest tag pointer to the latest commit
git tag -f latest
git push <remote> :refs/tags/latest
git push origin master --tags
Release on npm
Authors
Klaus Hartl
Fagner Brack
And awesome contributors
View Code

 

1.3.2、操作cookies

1、寫

示例:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>客戶端讀寫Cookie</title>
    </head>
    <body>
        <button type="button" onclick="writeCookie();"></button>
        <button  type="button" onclick="readCookie();"></button>
        <button  type="button" onclick="removeCookie();">清除</button>
        
        <script src="js.cookie-2.2.0.min.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            function writeCookie(){
                //在當前域下寫入cookie
                Cookies.set('price', '998', { expires: 7 });
            }
        </script>
    </body>
</html>

運行結果:

2、讀

示例:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>客戶端讀寫Cookie</title>
    </head>
    <body>
        <button type="button" onclick="writeCookie();"></button>
        <button  type="button" onclick="readCookie();"></button>
        <button  type="button" onclick="removeCookie();">清除</button>
        
        <script src="js.cookie-2.2.0.min.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            function writeCookie(){
                //在當前域下寫入cookie
                Cookies.set('price', '998', { expires: 7 });
            }
            function readCookie(){
                //在當前域根據key讀取cookie
                var price=Cookies.get("price");
                alert("價格:"+price);
            }
        </script>
    </body>
</html>

結果:

3、清除

示例:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>客戶端讀寫Cookie</title>
    </head>
    <body>
        <button type="button" onclick="writeCookie();"></button>
        <button  type="button" onclick="readCookie();"></button>
        <button  type="button" onclick="removeCookie();">清除</button>
        
        <script src="js.cookie-2.2.0.min.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            function writeCookie(){
                //在當前域下寫入cookie
                Cookies.set('price', '998', { expires: 7 });  //過期時間為7天
                Cookies.set('color', 'blue', { expires: 7 });
            }
            function readCookie(){
                //在當前域根據key讀取cookie
                var price=Cookies.get("price");
                alert("價格:"+price);
            }
            function removeCookie(){
                //在當前域指定的cookie
                Cookies.remove("price");
            }
            
            console.log(document.cookie);
        </script>
    </body>
</html>

結果:

二、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_*

或者

C:\Users\Administrator\AppData\Local\Google\Chrome\User Data\Profile 1\Local Storage

Administrator是當前登錄用戶名

使用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 

回調方法:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <script type="text/javascript">
            var ticker={
                n:0,
                add:function(){
                    this.n++;
                },
                show:function(){
                    alert(ticker.n);
                }
            };
            
            ticker.add();
            ticker.add();
            ticker.show();
            
            
            function add(a,b){
                var sum=a+b;
                alert(a+"+"+b+"="+sum);
            }
            
            calc(1,2,add);
            
            calc(5,8,function(c,d){
                alert(c+"-"+d+"="+(c-d));
            });
            
           function calc(n1,n2,fun){
                   if(n1>0&&n2>0&&fun){
                       fun(n1,n2);
                   }else{
                       alert("參數缺失");
                   }
           }
        
        </script>
    </body>
</html>

封裝結果:

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title>WebSqlDataBase</title>
    </head>

    <body>
        <h2>WebSqlDataBase</h2>
        <button onclick="app.openDb()">創建/打開數據庫</button>
        <button onclick="app.createTable()">創建數據表</button>
        <button onclick="app.insert()">添加數據</button>
        <button onclick="app.update()">修改數據</button>
        <button onclick="app.remove()">刪除數據</button>
        <button onclick="app.select()">查詢數據</button>
        <button onclick="app.dropTable()">刪除表</button>
        <p>
            編號:<input type="text" id="id" />
        </p>
        <p>
            名稱:<input type="text" id="name" />
        </p>
        <p>
            <h2 id="h2Msg"></h2>
        </p>
        <script type="text/javascript">
            var app = {
                db: {},
                data: {
                    id: document.querySelector("#id").value,
                    name: document.querySelector("#name").value
                },
                init: function() {
                    window.log = function(msg) {
                        console.log(msg);
                        document.getElementById("h2Msg").innerHTML += msg + "<br/>";
                    }
                    app.openDb();
                },
                openDb: function() { //創建或打開數據庫
                    app.db = openDatabase("gomallDb", "1.0", "天狗商城", 1024 * 1024 * 3, function() {
                        log("創建或打開數據庫成功");
                    });
                },
                executeSql: function(sql, params, success, error) {
                    if(app.db) {
                        app.db.transaction(function(tx) {
                            tx.executeSql(sql, params || [], function(tx, result) {
                                log("執行成功!");
                                if(success) {
                                    success(tx, result);
                                }
                            }, function(tx, result) {
                                log("執行失敗!");
                                if(error) {
                                    error(tx, result);
                                }
                            });
                        });
                    } else {
                        log("請打開數據庫");
                    }
                },
                createTable: function() { //創建表
                    var sql = "create table if not exists goods(id integer primary key autoincrement,name text not null);";
                    app.executeSql(sql);
                },
                insert: function() { //添加數據
                    app.executeSql("insert into goods(name) values(?)", [app.data.name]);
                },
                update: function() { //修改數據
                    app.executeSql("update goods set name=? where id=?", [app.data.name, app.data.id]);
                },
                remove: function() { //刪除數據
                    app.executeSql("delete from goods where name like ? or id=?", [app.data.name, app.data.id]);
                },
                select: function() { //查詢
                    app.executeSql("select id,name from goods", [], function(tx, result) {
                        var r = result.rows;
                        for(var i = 0; i < r.length; i++) {
                            log(r[i].id + "," + r[i].name);
                        }
                    });
                },
                dropTable: function() { //刪除表
                    app.executeSql("drop table if exists goods", [], function() {
                            alert("刪除成功!")
                        },
                        function() {
                            alert("刪除失敗!");
                        }
                    )
                }
            };
            app.init();
        </script>
    </body>

</html>
View Code

 

第一次封裝后的代碼,在整個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>

運行結果:

五、IndexedDB

Web Sql API的主要實現者是Chrome、Safari、Opera、Android、IOS、BB。IE和FF都不支持Web Sql API。
IndexedDB由於受到W3C的推崇。瀏覽器廠商的實現情況要好一些。但由於目前規范說明書還只是處於候選建議階段。各大瀏覽器廠商目前的實現還有一些差異化。

IndexedDB是在瀏覽器中保存結構化數據的一種數據庫,為了替換WebSQL(標准已廢棄,但被廣泛支持)而出現。IndexedDB使用NoSQL的形式來操作數據庫,保存和讀取是JavaScript對象,同時還支持查詢及搜索。

API: https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API

示例代碼:

if('indexedDB' in window){
    //檢測是否支持indexed database
}else{
    mui.alert('您的手機占不支持');
}
//數據庫信息
var DB = {
    name:'admin_users',
    version:1
}
var db;
function openDB(name,version){
    //第一個參數是數據庫名稱,如果存在則打開,如果不存在就創建
    //第二個參數是數據庫版本,用於更新數據庫結構
    var request = window.indexedDB.open(name,version);
    
        request.onerror = function(e){
            mui.alert('打開數據庫失敗');
        }
        
        request.onsuccess = function(e){
            db = request.result;
            ReadAll();
        }
        //操作數據庫(創建刪除修改)
        //首次打開數據庫或改變數據庫版本的時候觸發
        request.onupgradeneeded = function(e){
            //使用createObjectStore()方法創建一個對象存儲
            //此方法接受兩個參數:存儲的名稱和參數對象
            //keypath是用戶數據的唯一標識 或者使用索引
            var objectStore = e.target.result.createObjectStore("users",{keyPath:'name'});
        }
}

function Add(name,account,password){
    //transaction()方法是用來指定我們想要進行事務處理的對象存儲,接受3個參數
    //第一個(必選)要處理的對象存儲的列表數組
    //第二個(可選)指定操作方式 只讀/讀寫
    //第三個(可選)版本變化
    //add()方法用於添加數據
    var request = db.transaction(["users"],"readwrite").objectStore("users").add({
        name:name,
        account:account,
        password:password
    });
    
    request.onsuccess = function(e){
        mui.toast('成功');
        var list = document.querySelector('#list');
        var dom = '<li class="mui-table-view-cell mui-collapse">';
                    dom+= '<a class="mui-navigate-right" href="#">'+name+'</a>';
                    dom+= '<div class="mui-collapse-content"><p><span>賬號:</span>'+account+'</p>';
                    dom+= '<p><span>密碼:</span>'+password+'</p></div></li>';
            list.innerHTML += dom;
    }
    
    request.onerror = function(e){
        mui.toast('失敗');
    }
}

function Read(name){
    var objectStore = db.transaction(["users"]).objectStore("users");
    //get()方法用於獲取數據
    var request = objectStore.get(name);
        
        request.onerror = function(event){
            mui.toast('讀取失敗');
        }
        
        request.onsuccess = function(event){
            if(request.result){
                console.log(request.result);
            }
        }
}

function ReadAll(){
    var objectStore = db.transaction("users").objectStore("users");
    //openCursor()方法用於獲取所有數據
    var request = objectStore.openCursor();
    
        request.onsuccess = function(event){
            //db.close();
            var res = event.target.result;
            var list = document.querySelector('#list');
            if(res){
                var dom = '<li class="mui-table-view-cell mui-collapse">';
                    dom+= '<a class="mui-navigate-right" href="#">'+res.value.name+'</a>';
                    dom+= '<div class="mui-collapse-content"><p><span>賬號:</span>'+res.value.account+'</p>';
                    dom+= '<p><span>密碼:</span>'+res.value.password+'</p></div></li>';
                    
                list.innerHTML += dom;
                //console.log(res.value);
                res.continue();
            }
        }
        
        request.onerror = function(e){
            mui.toast('讀取失敗')
        }
}

function Remove(name){
    //delete()方法用於刪除數據
    var request = db.transaction("users","readwrite").objectStore('users').delete(name);
        request.onsuccess = function(event){
            mui.toast('刪除成功');
        }
        request.onerror = function(){
            mui.toast('刪除失敗')
        }
}
openDB(DB.name,DB.version);


var submits = document.querySelector('#submit');
function display(dis){
    var bg = document.querySelectorAll('.alert-bg')[0];
    var alert = document.querySelectorAll('.alert')[0];
    alert.style.display = dis;
    bg.style.display = dis;
}
submits.onclick = function(){
    var name      = document.querySelector('#name').value;
    var account  = document.querySelector('#account').value;
    var password = document.querySelector('#password').value;
    if(!name || !account || !password){
        return mui.toast('請輸入完整信息');
    }
    display('none');
    Add(name,account,password)
}
View Code

5.1、數據庫初始化

IndexedDB保存的是對象,而不是使用表保存數據。打開數據庫使用indexDB.open方法,這方法有兩個參數,第一個是數據庫名稱,第二個是數據版本號。

IndexedDB的操作完全是異步進行的,每一次IndexedDB操作,都需要注冊onerror或onsuccess事件處理程序。

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title>IndexedDB</title>
    </head>

    <body>
        <h2>IndexedDB(NOSQL)</h2>
        <input value="創建數據庫與表" type="button" onclick="create()" />
        <h2 id="msg"></h2>
        <script>
            //數據庫
            var db;

            //創建數據庫與表
            function create() {
                //創建一個名稱為gomall且版本為2的數據庫,返回一個請求
                var request = indexedDB.open("gomall", 2);
                //綁定回調事件,成功時
                request.onsuccess = function(e) {
                    db = e.target.result;
                    log('創建數據庫成功');
                };
                //失敗時
                request.onerror = function(e) {
                    log("錯誤:" + e.target.errorCode || e.target.error);
                };
                //增加數據庫版本號時,會觸發onupgradeneeded事件(會在onsuccess之前被調用)
                request.onupgradeneeded = function(e) {
                    //創建對象存儲空間(ObjectStore),類似表,goods是表名,id是主鍵,存儲的是JSON
                    e.target.result.createObjectStore("goods",{"keyPath":"id"});
                    log("初始化數據庫成功!");
                };
            }

            //顯示消息
            var msg = document.getElementById("msg");

            function log(m) {
                msg.innerHTML += m + "<br/>";
            }

            //用於判斷瀏覽器是否支持indexedDB,0,null,'',undefind false
            if(window.indexedDB) {

            } else {
                alert('請升級瀏覽器,如chrome');
            }
        </script>
    </body>

</html>

這里要注意的是,數據庫版本只會有最新一個,不會同時存在兩個版本的同名數據庫。

運行結果:

5.2、對象存儲空間(ObjectStore)

對象存儲空間(ObjectStore)可以想象成關系數據庫的表,在初始化DB觸發onupgradeneeded時,創建ObjectStore。使用createObjectStore方法,第一個參數是對象名,第二個參數是對象屬性,一般是設置keyPath(作為鍵使用)。

因為對新數據的操作都需要在transaction中進行,而transaction又要求指定object store,所以我們只能在創建數據庫的時候初始化object store以供后面使用,這正是onupgradeneeded的一個重要作用

有了數據庫后我們自然希望創建一個表用來存儲數據,但indexedDB中沒有表的概念,而是objectStore,一個數據庫中可以包含多個objectStore,objectStore是一個靈活的數據結構,可以存放多種類型數據。也就是說一個objectStore相當於一張表,里面存儲的每條數據和一個鍵相關聯。

我們可以使用每條記錄中的某個指定字段作為鍵值(keyPath),也可以使用自動生成的遞增數字作為鍵值(keyGenerator),也可以不指定。選擇鍵的類型不同,objectStore可以存儲的數據結構也有差異

不使用—>任意值,但是沒添加一條數據的時候需要指定鍵參數

keyPath—>Javascript對象,對象必須有一屬性作為鍵值

keyGenerator—>任意值(db.createObjectStore('students',{autoIncrement: true});)

都使用—>Javascript對象,如果對象中有keyPath指定的屬性則不生成新的鍵值,如果沒有自動生成遞增鍵值,填充keyPath指定屬性

     req.onupgradeneeded = function (evt) {
          console.debug("initDb.onupgradeneeded");
          var db = evt.currentTarget.result;
          //ObjectStore必須在onupgradeneeded里創建,其他地方將會創建失敗
          var usersStore = db.createObjectStore("users", { keyPath : "id" });
     };

效果如下:

5.3、事務

所有讀取或修改數據的操作,都要通過事務來完成。創建事務使用transaction方法,第一個參數是需要訪問的ObjectStore,第二個參數是訪問模式(readwrite可讀可寫、readonly只讀,默認是只讀)。

5.4、添加數據

示例:

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title>IndexedDB</title>
    </head>

    <body>
        <h2>IndexedDB(NOSQL)</h2>
        <input value="創建數據庫與表" type="button" onclick="create()" />
        <input value="新增數據" type="button" onclick="add()" />
        <h2 id="msg"></h2>
        <script>
            //數據庫
            var db;

            //創建數據庫與表
            function create() {
                //創建一個名稱為gomall且版本為2的數據庫,返回一個請求
                var request = indexedDB.open("gomall", 2);
                //綁定回調事件,成功時
                request.onsuccess = function(e) {
                    db = e.target.result;
                    log('創建數據庫成功');
                };
                //失敗時
                request.onerror = function(e) {
                    log("錯誤:" + e.target.errorCode || e.target.error);
                };
                //增加數據庫版本號時,會觸發onupgradeneeded事件(會在onsuccess之前被調用)
                request.onupgradeneeded = function(e) {
                    //創建對象存儲空間(ObjectStore),類似表,goods是表名,id是主鍵,存儲的是JSON
                    e.target.result.createObjectStore("goods",{"keyPath":"id"});
                    log("初始化數據庫成功!");
                };
            }
            
            //新增數據
            function add(){
                //創建事務對象
                var tx=db.transaction("goods","readwrite");
                //從數據庫中獲得存儲對象,表
                var goods=tx.objectStore("goods");
                //javascript中的對象數組
                var items=[{"id":1,"name":"iPhone 11","price":19999.5},{"id":2,"name":"華為榮耀V9","price":1997.3}];
                for(var i=0;i<items.length;i++){
                    goods.add(items[i]);
                }
                log("添加數據成功!");
            }

            //顯示消息
            var msg = document.getElementById("msg");

            function log(m) {
                msg.innerHTML += m + "<br/>";
            }

            //用於判斷瀏覽器是否支持indexedDB,0,null,'',undefind false
            if(window.indexedDB) {

            } else {
                alert('請升級瀏覽器,如chrome');
            }
        </script>
    </body>

</html>
View Code 

 結果:

5.5、獲取單個對象數據

示例:

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title>IndexedDB</title>
    </head>

    <body>
        <h2>IndexedDB(NOSQL)</h2>
        <input value="創建數據庫與表" type="button" onclick="create()" />
        <input value="新增數據" type="button" onclick="add()" />
        <input value="獲得單個對象" type="button" onclick="getSingle()" />
        <h2 id="msg"></h2>
        <script>
            //數據庫
            var db;

            //創建數據庫與表
            function create() {
                //創建一個名稱為gomall且版本為2的數據庫,返回一個請求
                var request = indexedDB.open("gomall", 2);
                //綁定回調事件,成功時
                request.onsuccess = function(e) {
                    db = e.target.result;
                    log('創建數據庫成功');
                };
                //失敗時
                request.onerror = function(e) {
                    log("錯誤:" + e.target.errorCode || e.target.error);
                };
                //增加數據庫版本號時,會觸發onupgradeneeded事件(會在onsuccess之前被調用)
                request.onupgradeneeded = function(e) {
                    //創建對象存儲空間(ObjectStore),類似表,goods是表名,id是主鍵,存儲的是JSON
                    e.target.result.createObjectStore("goods", {
                        "keyPath": "id"
                    });
                    log("初始化數據庫成功!");
                };
            }

            //新增數據
            function add() {
                //創建事務對象
                var tx = db.transaction("goods", "readwrite");
                //從數據庫中獲得存儲對象,表
                var goods = tx.objectStore("goods");
                //javascript中的對象數組
                var items = [{
                    "id": 1,
                    "name": "iPhone 11",
                    "price": 19999.5
                }, {
                    "id": 2,
                    "name": "華為榮耀V9",
                    "price": 1997.3
                }];
                for(var i = 0; i < items.length; i++) {
                    goods.add(items[i]);
                }
                log("添加數據成功!");
            }

            //獲得單個對象
            function getSingle() {
                //創建事務對象
                var tx = db.transaction("goods", "readwrite");
                //從數據庫中獲得存儲對象,表
                var goods = tx.objectStore("goods");
                //請求key為1的對象
                var request=goods.get(1);
                request.onsuccess=function(e){
                    var obj=e.target.result;
                    //JSON.stringify將obj對象轉換成字符
                    log(JSON.stringify(obj));
                    log(obj.id+""+obj.name+""+obj.price);
                };
            }

            //顯示消息
            var msg = document.getElementById("msg");

            function log(m) {
                msg.innerHTML += m + "<br/>";
            }

            //用於判斷瀏覽器是否支持indexedDB,0,null,'',undefind false
            if(window.indexedDB) {

            } else {
                alert('請升級瀏覽器,如chrome');
            }
        </script>
    </body>

</html>
View Code

結果:

5.6、修改數據

示例:

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title>IndexedDB</title>
    </head>

    <body>
        <h2>IndexedDB(NOSQL)</h2>
        <input value="創建數據庫與表" type="button" onclick="create()" />
        <input value="新增數據" type="button" onclick="add()" />
        <input value="獲得單個對象" type="button" onclick="getSingle()" />
        <input value="更新對象" type="button" onclick="edit()" />
        <h2 id="msg"></h2>
        <script>
            //數據庫
            var db;

            //創建數據庫與表
            function create() {
                //創建一個名稱為gomall且版本為2的數據庫,返回一個請求
                var request = indexedDB.open("gomall", 2);
                //綁定回調事件,成功時
                request.onsuccess = function(e) {
                    db = e.target.result;
                    log('創建數據庫成功');
                };
                //失敗時
                request.onerror = function(e) {
                    log("錯誤:" + e.target.errorCode || e.target.error);
                };
                //增加數據庫版本號時,會觸發onupgradeneeded事件(會在onsuccess之前被調用)
                request.onupgradeneeded = function(e) {
                    //創建對象存儲空間(ObjectStore),類似表,goods是表名,id是主鍵,存儲的是JSON
                    e.target.result.createObjectStore("goods", {
                        "keyPath": "id"
                    });
                    log("初始化數據庫成功!");
                };
            }

            //新增數據
            function add() {
                //創建事務對象
                var tx = db.transaction("goods", "readwrite");
                //從數據庫中獲得存儲對象,表
                var goods = tx.objectStore("goods");
                //javascript中的對象數組
                var items = [{
                    "id": 1,
                    "name": "iPhone 11",
                    "price": 19999.5
                }, {
                    "id": 2,
                    "name": "華為榮耀V9",
                    "price": 1997.3
                }];
                for(var i = 0; i < items.length; i++) {
                    goods.add(items[i]);
                }
                log("添加數據成功!");
            }

            //獲得單個對象
            function getSingle() {
                //創建事務對象
                var tx = db.transaction("goods", "readwrite");
                //從數據庫中獲得存儲對象,表
                var goods = tx.objectStore("goods");
                //請求key為1的對象
                var request = goods.get(2);
                request.onsuccess = function(e) {
                    var obj = e.target.result;
                    //JSON.stringify將obj對象轉換成字符
                    log(JSON.stringify(obj));
                    log(obj.id + "" + obj.name + "" + obj.price);
                };
            }

            //更新對象
            function edit() {
                //創建事務對象
                var tx = db.transaction("goods", "readwrite");
                //從數據庫中獲得存儲對象,表
                var goods = tx.objectStore("goods");
                //javascript中的對象數組
                var item = {
                    "id": 2,
                    "name": "華為榮耀P15",
                    "price":1357.9,
                    "os":"android"
                };
                //執行更新
                var request=goods.put(item);
                request.onsuccess=function(e){
                    log(e.target.result);
                };
            }

            //顯示消息
            var msg = document.getElementById("msg");

            function log(m) {
                msg.innerHTML += m + "<br/>";
            }

            //用於判斷瀏覽器是否支持indexedDB,0,null,'',undefind false
            if(window.indexedDB) {

            } else {
                alert('請升級瀏覽器,如chrome');
            }
        </script>
    </body>

</html>
View Code

結果:

5.7、刪除數據

示例:

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title>IndexedDB</title>
    </head>

    <body>
        <h2>IndexedDB(NOSQL)</h2>
        <input value="創建數據庫與表" type="button" onclick="create()" />
        <input value="新增數據" type="button" onclick="add()" />
        <input value="獲得單個對象" type="button" onclick="getSingle()" />
        <input value="更新對象" type="button" onclick="edit()" />
        <input value="刪除對象" type="button" onclick="del()" />
        <h2 id="msg"></h2>
        <script>
            //數據庫
            var db;

            //創建數據庫與表
            function create() {
                //創建一個名稱為gomall且版本為2的數據庫,返回一個請求
                var request = indexedDB.open("gomall", 2);
                //綁定回調事件,成功時
                request.onsuccess = function(e) {
                    db = e.target.result;
                    log('創建數據庫成功');
                };
                //失敗時
                request.onerror = function(e) {
                    log("錯誤:" + e.target.errorCode || e.target.error);
                };
                //增加數據庫版本號時,會觸發onupgradeneeded事件(會在onsuccess之前被調用)
                request.onupgradeneeded = function(e) {
                    //創建對象存儲空間(ObjectStore),類似表,goods是表名,id是主鍵,存儲的是JSON
                    e.target.result.createObjectStore("goods", {
                        "keyPath": "id"
                    });
                    log("初始化數據庫成功!");
                };
            }

            //新增數據
            function add() {
                //創建事務對象
                var tx = db.transaction("goods", "readwrite");
                //從數據庫中獲得存儲對象,表
                var goods = tx.objectStore("goods");
                //javascript中的對象數組
                var items = [{
                    "id": 1,
                    "name": "iPhone 11",
                    "price": 19999.5
                }, {
                    "id": 2,
                    "name": "華為榮耀V9",
                    "price": 1997.3
                }];
                for(var i = 0; i < items.length; i++) {
                    goods.add(items[i]);
                }
                log("添加數據成功!");
            }

            //獲得單個對象
            function getSingle() {
                //創建事務對象
                var tx = db.transaction("goods", "readwrite");
                //從數據庫中獲得存儲對象,表
                var goods = tx.objectStore("goods");
                //請求key為1的對象
                var request = goods.get(2);
                request.onsuccess = function(e) {
                    var obj = e.target.result;
                    //JSON.stringify將obj對象轉換成字符
                    log(JSON.stringify(obj));
                    log(obj.id + "" + obj.name + "" + obj.price);
                };
            }

            //更新對象
            function edit() {
                //創建事務對象
                var tx = db.transaction("goods", "readwrite");
                //從數據庫中獲得存儲對象,表
                var goods = tx.objectStore("goods");
                //javascript中的對象數組
                var item = {
                    "id": 2,
                    "name": "華為榮耀P15",
                    "price":1357.9,
                    "os":"android"
                };
                //執行更新
                var request=goods.put(item);
                request.onsuccess=function(e){
                    log(e.target.result);
                };
            }
            
            //刪除對象
            function del() {
                //創建事務對象
                var tx = db.transaction("goods", "readwrite");
                //從數據庫中獲得存儲對象,表
                var goods = tx.objectStore("goods");
                //執行刪除操作
                var request=goods.delete(2);
                //成功時的回調
                request.onsuccess=function(e){
                    log(e.target.result);
                };
            }
            
            //顯示消息
            var msg = document.getElementById("msg");

            function log(m) {
                msg.innerHTML += m + "<br/>";
            }

            //用於判斷瀏覽器是否支持indexedDB,0,null,'',undefind false
            if(window.indexedDB) {

            } else {
                alert('請升級瀏覽器,如chrome');
            }
        </script>
    </body>

</html>
View Code

 

結果:

5.8、清空數據

function clearData(){
     var tx = db.transaction("users", READ_WRITE);
     var store = tx.objectStore("users");
     var req = store.clear();
     req.onsuccess = function (evt) {
          console.debug("clearData success");
     };
     req.onerror = function (evt) {
          console.error("clearData error:", evt.target.errorCode || evt.target.error);
     };
}

5.9、游標查詢

使用事務可以直接通過鍵檢索單個對象,而需要檢索多個對象時候就需要使用游標。游標是指向結果集的指針,不提前收集結果。游標指針會先指向結果中的第一項,在接到查找下一項指令時,才會指向下一項。

function openCursor(){
     var tx = db.transaction("users", READ_WRITE);
     var store = tx.objectStore("users");
     var req = store.openCursor();
     req.onsuccess = function (evt) {
          var cursor = evt.target.result;
          if(cursor){ //必要檢查
               var value = cursor.value;
               console.log(value);
               if(value.name == '楊冪'){
                    value.age = 16;
                    cursor.update(value); //修改數據(必須是讀寫模式)
               }
               if(value.name == '柳岩'){
                    cursor.delete();  //刪除當前項
               }
               cursor.continue(); //移動到下一項
          }
     };
     req.onerror = function (evt) {
          console.error("openCursor error:", evt.target.errorCode || evt.target.error);
     };
}

這里有幾點要注意:

1. 如果需要修改或刪除數據,就需要打開成讀寫模式。

2. cursor的非空校驗是必要的。

3. 修改或刪除的操作也是有onsuccess和onerror的,只是在示例中沒有寫出來。

4. 調用continue才會移動到下一項

另外可以設置游標的鍵范圍和游標的方向,即打開openCursor方法時可以傳這兩個參數(openCursor(鍵范圍,方向)),第一個參數是object類型,第二個參數是字符串類型。

示例:

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title>IndexedDB</title>
    </head>

    <body>
        <h2>IndexedDB(NOSQL)</h2>
        <input value="創建數據庫與表" type="button" onclick="create()" />
        <input value="新增數據" type="button" onclick="add()" />
        <input value="獲得單個對象" type="button" onclick="getSingle()" />
        <input value="更新對象" type="button" onclick="edit()" />
        <input value="刪除對象" type="button" onclick="del()" />
        <input value="獲得多個對象(游標)" type="button" onclick="getAll()" />
        <h2 id="msg"></h2>
        <script>
            //數據庫
            var db;

            //創建數據庫與表
            function create() {
                //創建一個名稱為gomall且版本為2的數據庫,返回一個請求
                var request = indexedDB.open("gomall", 2);
                //綁定回調事件,成功時
                request.onsuccess = function(e) {
                    db = e.target.result;
                    log('創建數據庫成功');
                };
                //失敗時
                request.onerror = function(e) {
                    log("錯誤:" + e.target.errorCode || e.target.error);
                };
                //增加數據庫版本號時,會觸發onupgradeneeded事件(會在onsuccess之前被調用)
                request.onupgradeneeded = function(e) {
                    //創建對象存儲空間(ObjectStore),類似表,goods是表名,id是主鍵,存儲的是JSON
                    e.target.result.createObjectStore("goods", {
                        "keyPath": "id"
                    });
                    log("初始化數據庫成功!");
                };
            }

            //新增數據
            function add() {
                //創建事務對象
                var tx = db.transaction("goods", "readwrite");
                //從數據庫中獲得存儲對象,表
                var goods = tx.objectStore("goods");
                //javascript中的對象數組
                var items = [{
                    "id": 2,
                    "name": "iPhone 13",
                    "price": 19999.5
                }, {
                    "id": 3,
                    "name": "華為榮耀V10",
                    "price": 1997.3
                }];
                for(var i = 0; i < items.length; i++) {
                    goods.add(items[i]);
                }
                log("添加數據成功!");
            }

            //獲得單個對象
            function getSingle() {
                //創建事務對象
                var tx = db.transaction("goods", "readwrite");
                //從數據庫中獲得存儲對象,表
                var goods = tx.objectStore("goods");
                //請求key為1的對象
                var request = goods.get(2);
                request.onsuccess = function(e) {
                    var obj = e.target.result;
                    //JSON.stringify將obj對象轉換成字符
                    log(JSON.stringify(obj));
                    log(obj.id + "" + obj.name + "" + obj.price);
                };
            }

            //更新對象
            function edit() {
                //創建事務對象
                var tx = db.transaction("goods", "readwrite");
                //從數據庫中獲得存儲對象,表
                var goods = tx.objectStore("goods");
                //javascript中的對象數組
                var item = {
                    "id": 2,
                    "name": "華為榮耀P15",
                    "price": 1357.9,
                    "os": "android"
                };
                //執行更新
                var request = goods.put(item);
                request.onsuccess = function(e) {
                    log(e.target.result);
                };
            }

            //刪除對象
            function del() {
                //創建事務對象
                var tx = db.transaction("goods", "readwrite");
                //從數據庫中獲得存儲對象,表
                var goods = tx.objectStore("goods");
                //執行刪除操作
                var request = goods.delete(2);
                //成功時的回調
                request.onsuccess = function(e) {
                    log(e.target.result);
                };
            }

            //獲得多個對象(游標)
            function getAll() {
                //創建事務對象
                var tx = db.transaction("goods", "readwrite");
                //從數據庫中獲得存儲對象,表
                var goods = tx.objectStore("goods");
                //打開游標
                var request = goods.openCursor();
                //成功時的回調
                request.onsuccess = function(e) {
                    //獲得游標
                    var cursor = e.target.result;
                    if(cursor) { //如果不為空
                        var obj = cursor.value;
                        log(JSON.stringify(obj));
                        //下移
                        cursor.continue();
                    }
                };
            }

            //顯示消息
            var msg = document.getElementById("msg");

            function log(m) {
                msg.innerHTML += m + "<br/>";
            }

            //用於判斷瀏覽器是否支持indexedDB,0,null,'',undefind false
            if(window.indexedDB) {

            } else {
                alert('請升級瀏覽器,如chrome');
            }
        </script>
    </body>

</html>

 

結果:

 

5.10、游標鍵范圍

鍵范圍由IDBKeyRange的實例表示。

復制代碼
IDBKeyRange.only('001');  //只想要鍵為001的結果
IDBKeyRange.lowerBound('002'); //從鍵為002開始,到最后
IDBKeyRange.lowerBound('002', true); //從鍵為002開始,但忽略002,到最后
IDBKeyRange.upperBound('002'); //從頭開始,到鍵為002為止
IDBKeyRange.upperBound('002', true); //從頭開始,到鍵為002為止,但忽略002
IDBKeyRange.bound('001', '005'); //從001開始,到為005為止
IDBKeyRange.bound('001', '005', true, true); //從001開始,到為005為止,但忽略001、005
復制代碼

5.11、游標方向

next : 從第一項到最后一項(默認)

prev : 從最后一項到第一項

索引

當需要使用其他屬性(非主鍵)獲取數據時,就要預先創建索引,然后使用索引獲取數據。

創建索引(在數據庫初始化onupgradeneeded事件時)

第一個參數是索引名字,第二個參數是索引的屬性的名字,第三個是一個options對象。一般是指定unique,設置索引是否唯一。

usersStore.createIndex("name", "name", { unique : false });

索引獲取數據

復制代碼
function indexGetData(){
     var tx = db.transaction("users", READ_WRITE);
     var store = tx.objectStore("users");
     var index = store.index("name");
     var req = index.get("楊冪")
     req.onsuccess = function (evt) {
          console.debug("indexGet success" , evt.target.result);
     };
     req.onerror = function (evt) {
          console.error("indexGet error:", evt.target.errorCode || evt.target.error);
     };
}

function indexOpenCursor(){
     var tx = db.transaction("users", READ_WRITE);
     var store = tx.objectStore("users");
     var index = store.index("name");
     var req = index.openCursor();
     req.onsuccess = function (evt) {
          var cursor = evt.target.result;
          if(cursor){ //必要檢查
               var value = cursor.value;
               console.log(value);
               cursor.continue(); //移動到下一項
          }
     };
     req.onerror = function (evt) {
          console.error("openCursor error:", evt.target.errorCode || evt.target.error);
     };
}
復制代碼

PS:索引用法跟普通取值和游標取值一樣

對象存儲所有索引

復制代碼
function indexNames(){
     var tx = db.transaction("users", READ_WRITE);
    var store = tx.objectStore("users");
     var indexNames = store.indexNames;
     var index, i = 0, len = indexNames.length;
     while(i < len){
          index = store.index(indexNames[i++]);
          console.log(index);
     }
}
復制代碼

5.12、刪除數據庫

var request = indexedDB.deleteDatabase(name);
var request = indexedDB.deleteDatabase(name, options);

var DBDeleteRequest = window.indexedDB.deleteDatabase("toDoList");

DBDeleteRequest.onerror = function(event) {
  console.log("Error deleting database.");
};
 
DBDeleteRequest.onsuccess = function(event) {
  console.log("Database deleted successfully");
    
  console.log(event.result); // should be undefined
};

5.13、刪除存儲對象

dbInstance.deleteObjectStore(name);

var dbName = "sampleDB";
var dbVersion = 2;
var request = indexedDB.open(dbName, dbVersion);

request.onupgradeneeded = function(e) {
  var db = request.result;
  if (e.oldVersion < 1) {
    db.createObjectStore("store1");
  }

  if (e.oldVersion < 2) {
    db.deleteObjectStore("store1");
    db.createObjectStore("store2");
  }

  // etc. for version < 3, 4...
};

六、移動端打包與運行

6.1、在手機端直接訪問Web站點

將手機與電腦連接到同一個網段,比如可以使用wifi

查看本機ip地址,有時需要將本地連接禁用,查看ip地址的指令是ipconfig

在手機端使用瀏覽器查看結果如下:

6.2、打包成app安裝運行

這里使用HBuilder打包成apk的安裝包,安裝打包結果如下:

6.3、套用移動端UI框架MUI

官網: http://www.dcloud.io/

文檔: http://dev.dcloud.net.cn/mui/ui/

源碼: https://github.com/dcloudio/mui/

6.3.1、Hello MUI

示例:

<!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>Hello MUI</title>
        <link href="css/mui.min.css" rel="stylesheet" />
    </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">Hello MUI</h1>
        </header>

        <div class="mui-content">
            <div class="mui-content-padded">
                <button type="button" class="mui-btn">默認</button>
                <button type="button" class="mui-btn mui-btn-primary" id="btnHello">Hello</button>
                <button type="button" class="mui-btn mui-btn-success">綠色</button>
                <button type="button" class="mui-btn mui-btn-warning">黃色</button>
                <button type="button" class="mui-btn mui-btn-danger">紅色</button>
                <button type="button" class="mui-btn mui-btn-royal">紫色</button>
            </div>
        </div>

        <script src="js/mui.min.js"></script>
        <script type="text/javascript" charset="utf-8">
            mui.init({
            });
            
            document.getElementById("btnHello").addEventListener("tap",function(){
                mui.alert("Hello MUI!","提示","確認",function(){
                    mui.toast("關閉完成");
                });
            },false);
        </script>
    </body>

</html>

效果:

6.3.2、事件與轉場

代碼:

<!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>Hello MUI</title>
        <link href="css/mui.min.css" rel="stylesheet" />
    </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">Hello MUI</h1>
        </header>

        <div class="mui-content">
            <div class="mui-content-padded">
                <button type="button" class="mui-btn">默認</button>
                <button type="button" class="mui-btn mui-btn-primary" id="btnHello">Hello</button>
                <button type="button" class="mui-btn mui-btn-success" id="btnWin">窗口</button>
                <button type="button" class="mui-btn mui-btn-warning">黃色</button>
                <button type="button" class="mui-btn mui-btn-danger">紅色</button>
                <button type="button" class="mui-btn mui-btn-royal">紫色</button>
            </div>
        </div>

        <script src="js/mui.min.js"></script>
        <script type="text/javascript" charset="utf-8">
            mui.init({
                //側滑關閉
                swipeBack: true //Boolean(默認false)啟用右滑關閉功能
            });

            document.getElementById("btnHello").addEventListener("tap", function() {
                mui.alert("Hello MUI!", "提示", "確認", function() {
                    mui.toast("關閉完成");
                });
            }, false);

            //mui加載完成
            mui.ready(function() {
                mui(".mui-content").on("tap", "#btnWin", function() {

                    mui.openWindow({
                        url: "sub1.html?id=1",
                        id: "sub1.html",
                        extras: {
                            id: "1"
                        },
                        createNew: false, //是否重復創建同樣id的webview,默認為false:不重復創建,直接顯示
                        show: {
                            autoShow: true //頁面loaded事件發生后自動顯示,默認為true
                        },
                        waiting: {
                            autoShow: true, //自動顯示等待框,默認為true
                            title: '正在加載...' //等待對話框上顯示的提示內容
                        }
                    });

                });
            });
        </script>
    </body>

</html>

效果:

6.3.3、列表與選項卡

示例:

<!DOCTYPE html>
<html>

    <head>
        <meta charset="utf-8">
        <title>Hello List</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">
        <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="slider" class="mui-slider">
                <div class="mui-slider-group mui-slider-loop">
                    <!-- 額外增加的一個節點(循環輪播:第一個節點是最后一張輪播) -->
                    <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>
                <!--輪播-->

                <!--list-->
                <ul class="mui-table-view mui-table-view-chevron">
                    <li class="mui-table-view-cell mui-media">
                        <a class="mui-navigate-right" id="sub1.html">
                            <img class="mui-media-object mui-pull-left" src="images/cbd.jpg">
                            <div class="mui-media-body">
                                CBD
                                <p class='mui-ellipsis'>烤爐模式的城,到黃昏,如同打翻的調色盤一般.</p>
                            </div>
                        </a>
                    </li>
                    <li class="mui-table-view-cell mui-media">
                        <a class='mui-navigate-right' id="index.html">
                            <img class="mui-media-object mui-pull-left" src="images/yuantiao.jpg">
                            <div class="mui-media-body">
                                遠眺
                                <p class='mui-ellipsis'>靜靜的看這個世界,最后終於瘋了</p>
                            </div>
                        </a>
                    </li>
                    <li class="mui-table-view-cell mui-media">
                        <a class="mui-navigate-right">
                            <img class="mui-media-object mui-pull-left" src="images/shuijiao.jpg">
                            <div class="mui-media-body">
                                幸福
                                <p class='mui-ellipsis'>能和心愛的人一起睡覺,是件幸福的事情;可是,打呼嚕怎么辦?</p>
                            </div>
                        </a>
                    </li>
                </ul>
                <!--list-->
            </div>
            <div id="tabbar-with-chat" class="mui-control-content">
                添加
            </div>
            <div id="tabbar-with-contact" class="mui-control-content">
                我的
            </div>
            <div id="tabbar-with-map" class="mui-control-content">
                設置
            </div>
        </div>
    </body>
    <script src="js/mui.min.js"></script>
    <script>
        mui.init({
            swipeBack: true //啟用右滑關閉功能
        });

        mui("#slider").slider({
            interval: 1000
        });

        mui.ready(function() {

            mui(".mui-content").on("tap", ".mui-navigate-right", function() {
                var id =this.id;
                mui.openWindow({
                    url: id,
                    id: id,
                    extras: {
                        id: "1"
                    },
                    createNew: false, //是否重復創建同樣id的webview,默認為false:不重復創建,直接顯示
                    show: {
                        autoShow: true //頁面loaded事件發生后自動顯示,默認為true
                    },
                    waiting: {
                        autoShow: true, //自動顯示等待框,默認為true
                        title: '正在加載...' //等待對話框上顯示的提示內容
                    }
                });

            });

        });
    </script>

</html>
View Code

 

效果:

這里使用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>

打包運行后的結果如下:

七、示例下載

https://git.coding.net/zhangguo5/HTML5_143.git

https://coding.net/u/zhangguo5/p/HTML502/git

github: https://github.com/zhangguo5/HTML5_2_1

mui示例: https://git.coding.net/zhangguo5/GoMallPro.git

打包下載

八、視頻

https://www.bilibili.com/video/av16293468/

九、作業

9.1.1、重現每個上課示例。

9.1.2、用戶登錄,記住密碼,選擇顏色,下次打開頁面時不需要輸入密碼,將背景色設置為用戶選擇的顏色。Login.html,Admin.html

9.1.3、用SessionStorage判斷用戶是否登錄,如果未登錄轉到頁面Login.html

9.1.4、使用IndexedDb完成如下功能:

參考:

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title>IndexedDB-UI</title>
    </head>

    <body>
        <h2>IndexedDB-UI(NOSQL)</h2>

        <table border="1" cellspacing="1" cellpadding="1" id="tabGoods" width="100%">
            <tr>
                <th>序號</th>
                <th>編號</th>
                <th>名稱</th>
                <th>價格</th>
                <th>操作</th>
            </tr>
        </table>

        <fieldset>
            <legend>商品信息</legend>
            <p>
                <label for="id">編號</label>
                <input type="text" name="id" id="id" value="" />
            </p>
            <p>
                <label for="name">名稱</label>
                <input type="text" name="name" id="name" value="" />
            </p>
            <p>
                <label for="price">價格</label>
                <input type="number" name="price" id="price" value="" />
            </p>
            <p>
                <input type="button" id="btnSubmit" value="添加" />
                <input type="button" id="btnUpdate" value="更新" />
            </p>
        </fieldset>

        <h3 id="msg"></h3>
        <script src="../js/jQuery/jquery-1.11.3.min.js" type="text/javascript" charset="utf-8"></script>
        <script>
            //數據庫
            var db;

            function init() {
                create();

                $("body").on("click", "#btnSubmit", {}, function() {
                    add();
                });

                $("#tabGoods").on("click", ".del", {}, function() {
                    if(confirm('您確定要刪除嗎?')) {
                        var tr = $(this).closest("tr");
                        del(tr.data("goods").id, function() {
                            alert('刪除成功!');
                            tr.remove();
                        });
                    }
                });

                $("#tabGoods").on("click", ".edit", {}, function() {
                    var tr = $(this).closest("tr");
                    var obj = tr.data("goods");
                    $("#id").val(obj.id).prop("disabled", "disabled");
                    $("#name").val(obj.name);
                    $("#price").val(obj.price);
                });

                $("body").on("click", "#btnUpdate", {}, function() {
                    var obj = {
                        "id": $("#id").val(),
                        "name": $("#name").val(),
                        "price": $("#price").val()
                    };
                    edit(obj, function() {
                        alert('修改成功!');
                        getAll();
                    });
                    $("#id").val(obj.id).removeProp("disabled");
                });

            }
            init();

            //創建數據庫與表
            function create() {
                //創建一個名稱為gomall且版本為2的數據庫,返回一個請求
                var request = indexedDB.open("gomallPro", 2);
                //綁定回調事件,成功時
                request.onsuccess = function(e) {
                    db = e.target.result;
                    log('創建數據庫或打開數據庫成功!');
                    getAll();
                };
                //失敗時
                request.onerror = function(e) {
                    log("錯誤:" + e.target.errorCode || e.target.error);
                };
                //增加數據庫版本號時,會觸發onupgradeneeded事件(會在onsuccess之前被調用)
                request.onupgradeneeded = function(e) {
                    //創建對象存儲空間(ObjectStore),類似表,goods是表名,id是主鍵,存儲的是JSON
                    e.target.result.createObjectStore("goods", {
                        "keyPath": "id"
                    });
                    log("初始化數據庫成功!");
                };
            }

            //新增數據
            function add() {
                //創建事務對象
                var tx = db.transaction("goods", "readwrite");
                //從數據庫中獲得存儲對象,表
                var goods = tx.objectStore("goods");
                //javascript中的對象數組
                var item = {
                    "id": $("#id").val(),
                    "name": $("#name").val(),
                    "price": $("#price").val()
                };
                goods.add(item);
                log("添加數據成功!");
                getAll();
            }

            //更新對象
            function edit(item, callback) {
                //創建事務對象
                var tx = db.transaction("goods", "readwrite");
                //從數據庫中獲得存儲對象,表
                var goods = tx.objectStore("goods");

                //執行更新
                var request = goods.put(item);
                request.onsuccess = function(e) {
                    log(e.target.result);
                    if(callback) callback();
                };
            }

            //刪除對象
            function del(key, callback) {
                //創建事務對象
                var tx = db.transaction("goods", "readwrite");
                //從數據庫中獲得存儲對象,表
                var goods = tx.objectStore("goods");
                //執行刪除操作
                var request = goods.delete(key);
                //成功時的回調
                request.onsuccess = function(e) {
                    log(e.target.result);
                    log("刪除成功!");
                    if(callback) callback();
                };
            }

            var index;
            //獲得多個對象(游標)
            function getAll() {
                index = 1;
                //移除表格中除第一行以外的所有行
                $("#tabGoods tr:gt(0)").remove();
                //創建事務對象
                var tx = db.transaction("goods", "readwrite");
                //從數據庫中獲得存儲對象,表
                var goods = tx.objectStore("goods");
                //打開游標
                var request = goods.openCursor();
                //成功時的回調
                request.onsuccess = function(e) {
                    //獲得游標
                    var cursor = e.target.result;
                    if(cursor) { //如果不為空
                        var obj = cursor.value;
                        genTr(obj);
                        //下移
                        cursor.continue();
                    }
                };
            }

            function genTr(goods) {
                var tr = $("<tr/>").data("goods", goods);
                $("<td/>").html(index++).appendTo(tr);
                $("<td/>").html(goods.id).appendTo(tr);
                $("<td/>").html(goods.name).appendTo(tr);
                $("<td/>").html(goods.price).appendTo(tr);

                var btnDel = $("<input type='button' value='刪除' class='del'/>");
                var btnEdit = $("<input type='button' value='編輯' class='edit'/>");

                $("<td/>").append(btnDel).append(btnEdit).appendTo(tr);

                tr.appendTo($("#tabGoods"));
            }

            //顯示消息
            var msg = document.getElementById("msg");

            function log(m) {
                msg.innerHTML += m + "<br/>";
            }
        </script>
    </body>
</html>
View Code

運行結果:

9.2.1、完成一個密碼管理器APP

javascript獲取url中的參數

//方法一:采用正則表達式獲取地址欄參數
function GetQueryString(name)
{
     var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");
     var r = window.location.search.substr(1).match(reg);
     if(r!=null)return  unescape(r[2]); return null;
}

 十、參考示例

10.1、添加與展示

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>IndexedDb</title>
</head>
<body>
<div>
<table border="1" width="100%" id="tabGoods">
    <tr>
        <th>編號</th><th>名稱</th><th>價格</th><th>操作</th>
    </tr>
</table>
</div>
<p>
<button onclick="nfapp.insert()" type="button">添加數據</button>
<button onclick="nfapp.select()" type="button">獲得所有數據</button>
</p>
<script src="../js/jquery-1.12.4.min.js"></script>
<script>
    ;(function () {
        var app = {
            db: null,
            run: function () {
                this.createDb();
            },
            //創建數據庫
            createDb: function () {
                //創建或打開數據庫gomall,指定版本為1
                var request = indexedDB.open("gomall", 1);
                //當發生錯誤時的回調事件
                request.onerror = function (e) {
                    console.log("錯誤:" + e.target.errorCode + "" + e.target.error);
                };
                //成功時的回調函數
                request.onsuccess = function (e) {
                    app.db = e.target.result;
                    console.log("創建或打開數據庫成功!");
                    app.select();
                };

                //當數據庫版本發生變化時的回調函數,發生在onsuccess之前
                request.onupgradeneeded = function (e) {
                    //當前數據庫,因為onsuccess還未執行,獲得不到數據庫
                    var db = e.currentTarget.result;
                    //創建存儲對象,指定名稱與參數,keyPath表示主鍵
                    db.createObjectStore("goods", {keyPath: "id"});
                }
            },
            //添加數據
            insert: function () {
                //創建事務對象
                var tx = this.db.transaction("goods", "readwrite");
                //獲得存儲對象
                var goods = tx.objectStore("goods");
                //添加數據對象
                goods.add({id: 103, name: "Meizu 16th", price: 3998});
                goods.add({id: 102, name: "Oppo R15", price: 2939});
                goods.add({id: 101, name: "Huwei 8X", price: 1398});
            },
            //獲取所有數據
            select:function () {
                //創建事務對象
                var tx = this.db.transaction("goods", "readwrite");
                //獲得存儲對象
                var goods = tx.objectStore("goods");
                //打開游標
                var request=goods.openCursor();
                //成功時的回調函數
                request.onsuccess=function (e) {
                    //獲得游標
                   var cursor=e.target.result;
                   //如果存在,沒有到末尾
                   if(cursor){
                       console.log(cursor.value);
                       //生成DOM行
                       app.createRow(cursor.value);
                       //游標下移
                       cursor.continue();
                   }
                };
            },
            createRow:function (obj) {
                var tr=$("<tr/>");
                $("<td/>").text(obj.id).appendTo(tr);
                $("<td/>").text(obj.name).appendTo(tr);
                $("<td/>").text(obj.price).appendTo(tr);
                $("<td/>").text("").appendTo(tr);
                $("#tabGoods").append(tr);
            }
        };

        app.run();
        window.nfapp = app;
    })();
</script>
</body>
</html>
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM