html5三种本地存储详解

 一个网站如何能在客户的浏览器存储更多的数据呢?

在Html4的时代在浏览器端存储点网站个性化的数据,尤其是用户浏览器的痕迹,用户的相关数据等一般只能存储在Cookie中,但是大多是浏览器对于Cookie的限制也就逼迫网站存储数据尽量精简,想存储复杂的、关系型的用户数据就根本不可能了。但是进入Html5时代,这一切都不叫事…

一、本地存储由来的背景

众所周知Html4时代Cookie的大小、格式、存储数据格式等限制,网站应用如果想在浏览器端存储用户的部分信息,那么只能借助于Cookie。但是Cookie的这些限制,也就导致了Cookie只能存储一些ID之类的标识符等简单的数据,复杂的数据就更别扯了。

下面是Cookie的限制:

    1, 大多数浏览器支持最大为 4096 字节的 Cookie。
    2, 浏览器还限制站点可以在用户计算机上存储的 Cookie 的数量。大多数浏览器只允许每个站点存储 20 个 Cookie;如果试图存储更多 Cookie,则最旧的 Cookie 便会被丢弃。
    3, 有些浏览器还会对它们将接受的来自所有站点的 Cookie 总数作出绝对限制,通常为 300 个。
    4, Cookie默认情况都会随着Http请求发送到后台服务器,但并不是所有请求都需要Cookie的,比如:js、css、图片等请求则不需要cookie。

Html5的设计者们,一开始就为Html5能成为富客户端做好了准备。为了破解Cookie的一系列限制,Html5通过JS的新的API就能直接存储大量的数据到客户端浏览器,而且支持复杂的本地数据库,让JS简直就是逆天了。Html5支持两种的WebStorage,一种是永久性的本地存储(localStorage),另外一种是会话级别的本地存储(sessionStorage)。

判断浏览器支不支持sessionStorage和浏览器不支持localstorage

if(window.sessionStorage){
    console.log('浏览器支持sessionStorage')
}
if(window.localStorage){
    console.log('浏览器支持localstorage')
} 

一、会话级别的本地存储:sessionStorage

存储数据

1.采用setItem()方法存储

sessionStorage.setItem("sessionKey", "会话级别的本地存储值1");

2.通过属性方式存储

sessionStorage['sessionKey2'] = '会话级别的本地存储值2';

读取数据

1.通过getItem()方法取值

var sessionVal = sessionStorage.getItem("sessionKey");

2.通过属性方式取值

var sessionVal2 = sessionStorage.sessionKey2;

存储Json对象

sessionStorage也可存储Json对象:存储时,通过JSON.stringify()将对象转换为文本格式;读取时,通过JSON.parse()将文本转换回对象。

var sessionJson = {
        name: '雨中的鱼',
        age: 25
 };
// 存储值:将对象转换为Json字符串
sessionStorage.setItem('user', JSON.stringify(sessionJson));
// 取值时:把获取到的Json字符串转换回对象
var JsonStr = sessionStorage.getItem('user');
user = JSON.parse(JsonStr);
console.log(user.name); // => 雨中的鱼

查看sessionStorage对象和长度

console.log(sessionStorage);
console.log(sessionStorage.length);

将指定的键名(key)从 sessionStorage 对象中移除。

sessionStorage.removeItem('sessionKey');

清空sessionStorage所有的key-value数据。

sessionStorage.clear();

二、永久本地存储:localStorage

存储数据

1.采用setItem()方法存储

localStorage.setItem("localkey", "永久本地存储值1");

2.通过属性方式存储

localStorage['localkey2'] = '永久本地存储值2';

读取数据

1.通过getItem()方法取值

var localVal = localStorage.getItem("localkey");

2.通过属性方式取值

var localVal2 = localStorage.localkey2;

存储Json对象

localStorage也可存储Json对象:存储时,通过JSON.stringify()将对象转换为文本格式;读取时,通过JSON.parse()将文本转换回对象。

var localJson = {
    name: '雨中的鱼local',
    age: 18
};
// 存储值:将对象转换为Json字符串
localStorage.setItem('user', JSON.stringify(localJson));
// 取值时:把获取到的Json字符串转换回对象
var JsonStr = localStorage.getItem('user');
user = JSON.parse(JsonStr);
console.log(user.name); // => 雨中的鱼

查看sessionStorage对象和长度

console.log(localStorage);
console.log(localStorage.length);

将指定的键名(key)从 localStorage 对象中移除。

localStorage.removeItem('user');

清空localStorage所有的key-value数据。

localStorage.clear();

localStorage和sessionStorage的key和length属性实现遍历,sessionStorage和localStorage提供的key()和length可以方便的实现存储的数据遍历,例如下面的代码:

var storage = window.localStorage;
for (var i = 0, len = storage.length; i < len; i++) {
    var key = storage.key(i);
    var value = storage.getItem(key);
    console.log(key + "=" + value);
}

storage事件监听

引用《h5移动web开发指南》上的话 “当同源页面的某个页面修改了localStorage,其余的同源页面只要注册了storage事件,就会触发”。所以,localStorage的例子运行需要如下条件:

1、同一浏览器打开了两个同源页面
2、其中一个网页修改了localStorage
3、另一网页注册了storage事件

很容易犯的错误是,在同一个网页修改本地存储,又在同一个网页监听,这样是没有效果的。

例子:

网页A:监听了storage事件:

<!DOCTYPE html>
<html>
<head lang="en">
    <title>A</title>
</head>
<body>
<script>
    if (window.addEventListener) {
        window.addEventListener("storage", handle_storage, false);
    } else if (window.attachEvent) {
        window.attachEvent("onstorage", handle_storage);
    }

    function handle_storage(e) {
        alert(e.newValue);
        if (!e) {
            e = window.event;
        }
    }
</script>
</body>
</html>

网页B:修改了localStorage

<!DOCTYPE html>
<html>
<head lang="en">
    <title>B</title>
</head>
<body>
<script>
    localStorage.clear();
    localStorage.setItem('foo', 'bar');
</script>
</body>
</html>

运行 : 将上面两个网页保存,放到同一个服务器上,然后,先打开A.html,再打开B.html。就会看到A.html会弹出提示框。注意两个网页要同源。

扩展

如果非得要在同一网页监听怎么办?可以重写localStorage的方法,抛出自定义事件:

var orignalSetItem = localStorage.setItem; 
localStorage.setItem = function(key,newValue){
    var setItemEvent = new Event("setItemEvent");
    setItemEvent.newValue = newValue;
    window.dispatchEvent(setItemEvent);
    orignalSetItem.apply(this,arguments);
}
window.addEventListener("setItemEvent", function (e) {
   console.log(e)
});
localStorage.setItem("name","雨中的鱼");

三、逆天了本地数据库

虽然Html5已经提供了功能强大的localStorage和sessionStorage,但是他们两个都只能提供存储简单数据结构的数据,对于复杂的Web应用的数据却无能为力。逆天的是Html5提供了一个浏览器端的数据库支持,允许我们直接通JS的API在浏览器端创建一个本地的数据库,而且支持标准的SQL的CRUD操作,让离线的Web应用更加方便的存储结构化的数据。接下里介绍一下本地数据的相关API和用法。

操作本地数据库的最基本的步骤是:
 第一步:openDatabase方法:创建一个访问数据库的对象。
第二步:使用第一步创建的数据库访问对象来执行transaction方法,通过此方法可以设置一个开启事务成功的事件响应方法,在
事件响应方法中可以执行SQL.
第三步:通过executeSql方法执行查询,当然查询可以是:CRUD。*/
//Demo:获取或者创建一个数据库,如果数据库不存在那么创建:

var dataBase = openDatabase(“student”, “1.0”, “学生表”, 1024 * 1024, function () {});

1,数据库名称。
2,数据库的版本号,目前来说传个1.0就可以了,当然可以不填;
3,对数据库的描述。
4,设置分配的数据库的大小(单位是kb)。
5,回调函数(可省略)。
初次调用时创建数据库,以后就是建立连接了。
(2)db.transaction方法可以设置一个回调函数,此函数可以接受一个参数就是我们开启的事务的对象。然后通过此对象可以进行执行Sql脚本,跟下面的步骤可以结合起来。
(3)通过executeSql方法执行查询。
    ts.executeSql(sqlQuery,[value1,value2..],dataHandler,errorHandler)
 参数说明:
    sqlQuery:需要具体执行的sql语句,可以是create、select、update、delete;

    [ value1,value2..]:sql语句中所有使用到的参数的数组,在executeSql方法中,将s>语句中所要使用的参数先用“?”代替,然后依次将这些参数组成数组放在第二个参数中
    ataHandler:执行成功是调用的回调函数,通过该函数可以获得查询结果集;
    ,errorHandler:执行失败时调用的回调函数;
完整例子代码如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

<input type="button" value="添加永久本地存储值4" id="add" />

<table>
    <tr>
        <td>用户名:</td>
        <td><input type="text" name="txtName" id="txtName" required/></td>
    </tr>
    <tr>
        <td>标题:</td>
        <td><input type="text" name="txtTitle" id="txtTitle" required/></td>
    </tr>
    <tr>
        <td>留言:</td>
        <td><input type="text" name="txtWords" id="txtWords" required/></td>
    </tr>
</table>
<input type="button" value="保存" id="btnSave"/>
<hr/>
<input type="button" value="展示所哟数据" onclick="showAllTheData();"/>
<input type="button" value="清空数据" onclick="delAllTheData();"/>

<table id="tblData">
</table>


<script type="text/javascript">
    //一个网站如何能在客户的浏览器存储更多的数据呢?
    //在Html4的时代在浏览器端存储点网站个性化的数据,尤其是用户浏览器的痕迹,用户的相关数据等一般只能存储在Cookie中,但是大多是浏览器对于Cookie的限制也就逼迫网站存储数据尽量精简,想存储复杂的、关系型的用户数据就根本不可能了。但是进入Html5时代,这一切都不叫事...

    //一、本地存储由来的背景
    /*
    *  众所周知Html4时代Cookie的大小、格式、存储数据格式等限制,网站应用如果想在浏览器端存储用户的部分信息,那么只能借助于Cookie。但是Cookie的这些限制,也就导致了Cookie只能存储一些ID之类的标识符等简单的数据,复杂的数据就更别扯了。

下面是Cookie的限制:

    1, 大多数浏览器支持最大为 4096 字节的 Cookie。
    2, 浏览器还限制站点可以在用户计算机上存储的 Cookie 的数量。大多数浏览器只允许每个站点存储 20 个 Cookie;如果试图存储更多 Cookie,则最旧的 Cookie 便会被丢弃。
    3, 有些浏览器还会对它们将接受的来自所有站点的 Cookie 总数作出绝对限制,通常为 300 个。
    4, Cookie默认情况都会随着Http请求发送到后台服务器,但并不是所有请求都需要Cookie的,比如:js、css、图片等请求则不需要cookie。

Html5的设计者们,一开始就为Html5能成为富客户端做好了准备。为了破解Cookie的一系列限制,Html5通过JS的新的API就能直接存储大量的数据到客户端浏览器,而且支持复杂的本地数据库,让JS简直就是逆天了。Html5支持两种的WebStorage,一种是永久性的本地存储(localStorage),另外一种是会话级别的本地存储(sessionStorage)。
    * */

    //判断浏览器支不支持sessionStorage和浏览器不支持localstorage
    if(window.localStorage){
        console.log('浏览器支持sessionStorage')
    }
    if(window.localStorage){
        console.log('浏览器支持localstorage')
    }

    console.log('会话级别的本地存储:sessionStorage----------------------');
    //一、会话级别的本地存储:sessionStorage

    //存储数据
    //1.采用setItem()方法存储
    sessionStorage.setItem("sessionKey", "会话级别的本地存储值1");
    //2.通过属性方式存储 
    sessionStorage['sessionKey2'] = '会话级别的本地存储值2';

    //读取数据
    //1.通过getItem()方法取值
    var sessionVal = sessionStorage.getItem("sessionKey");
    console.log(sessionVal);
    //2.通过属性方式取值
    var sessionVal2 = sessionStorage.sessionKey2;
    console.log(sessionVal2);

    //存储Json对象
    //sessionStorage也可存储Json对象:存储时,通过JSON.stringify()将对象转换为文本格式;读取时,通过JSON.parse()将文本转换回对象。
    var sessionJson = {
        name: '雨中的鱼',
        age: 25
    };
    // 存储值:将对象转换为Json字符串
    sessionStorage.setItem('user', JSON.stringify(sessionJson));
    // 取值时:把获取到的Json字符串转换回对象
    var JsonStr = sessionStorage.getItem('user');
    user = JSON.parse(JsonStr);
    console.log(user.name); // => 雨中的鱼

    //查看sessionStorage对象和长度
    console.log(sessionStorage);
    console.log(sessionStorage.length);

    //将指定的键名(key)从 sessionStorage 对象中移除。
    //sessionStorage.removeItem('sessionKey');

    //清空sessionStorage所有的key-value数据。
    //      sessionStorage.clear();


    console.log('永久本地存储:localStorage---------------------------');
    //存储数据
    //1.采用setItem()方法存储
    localStorage.setItem("localkey", "永久本地存储值1");
    //2.通过属性方式存储 
    localStorage['localkey2'] = '永久本地存储值2';

    //读取数据
    //1.通过getItem()方法取值
    var localVal = localStorage.getItem("localkey");
    console.log(localVal);
    //2.通过属性方式取值
    var localVal2 = localStorage.localkey2;
    console.log(localVal2);

    //存储Json对象
    //localStorage也可存储Json对象:存储时,通过JSON.stringify()将对象转换为文本格式;读取时,通过JSON.parse()将文本转换回对象。
    var localJson = {
        name: '雨中的鱼local',
        age: 18
    };
    // 存储值:将对象转换为Json字符串
    localStorage.setItem('user', JSON.stringify(localJson));
    // 取值时:把获取到的Json字符串转换回对象
    var JsonStr = localStorage.getItem('user');
    user = JSON.parse(JsonStr);
    console.log(user.name); // => 雨中的鱼

    //查看localStorage对象和长度
    console.log(localStorage);
    console.log(localStorage.length);
    //将指定的键名(key)从 localStorage 对象中移除。
    //localStorage.removeItem('user');

    //清空localStorage所有的key-value数据。
    //localStorage.clear();

    //localStorage和sessionStorage的key和length属性实现遍历
    //sessionStorage和localStorage提供的key()和length可以方便的实现存储的数据遍历,例如下面的代码:
    var storage = window.localStorage;
    for (var i = 0, len = storage.length; i < len; i++) {
        var key = storage.key(i);
        var value = storage.getItem(key);
        console.log(key + "=" + value);
    }


    //storage事件监听
    //分析
    //引用《h5移动web开发指南》上的话:
    //“当同源页面的某个页面修改了localStorage,其余的同源页面只要注册了storage事件,就会触发”
   // 所以,localStorage的例子运行需要如下条件:
    /*
        同一浏览器打开了两个同源页面
        其中一个网页修改了localStorage
        另一网页注册了storage事件
    */
    //很容易犯的错误是,在同一个网页修改本地存储,又在同一个网页监听,这样是没有效果的。


    //storage还提供了storage事件,当键值改变或者clear的时候,就可以触发storage事件,如下面的代码就添加了一个storage事件改变的监听:

    if (window.addEventListener) {
        window.addEventListener("storage", handle_storage, false);
        console.log(localStorage)
    } else if (window.attachEvent) {
        window.attachEvent("onstorage", handle_storage);
    }

    function handle_storage(e) {
        alert(e.newValue);
        if (!e) {
            e = window.event;
        }
    }


    //运行 : 将上面两个网页保存,放到同一个服务器上,然后,先打开A.html,再打开B.html。就会看到A.html会弹出提示框。注意两个网页要同源。

    document.getElementById('add').onclick = function(){
       localStorage.setItem("localkey4",'永久本地存储值4');
        var localkey4 = localStorage.getItem("localkey4");
        console.log(localkey4);
    }

    //扩展
    //如果非得要在同一网页监听怎么办?可以重写localStorage的方法,抛出自定义事件:
    var orignalSetItem = localStorage.setItem;
    localStorage.setItem = function(key,newValue){
        var setItemEvent = new Event("setItemEvent");
        setItemEvent.newValue = newValue;
        window.dispatchEvent(setItemEvent);
        orignalSetItem.apply(this,arguments);
    }
    window.addEventListener("setItemEvent", function (e) {
       console.log(e)
    });
    localStorage.setItem("nm","1234");

    //三、逆天了本地数据库
    /*虽然Html5已经提供了功能强大的localStorage和sessionStorage,但是他们两个都只能提供存储简单数据结构的数据,对于复杂的Web应用的数据却无能为力。逆天的是Html5提供了一个浏览器端的数据库支持,允许我们直接通JS的API在浏览器端创建一个本地的数据库,而且支持标准的SQL的CRUD操作,让离线的Web应用更加方便的存储结构化的数据。接下里介绍一下本地数据的相关API和用法*/
    /*操作本地数据库的最基本的步骤是:
        第一步:openDatabase方法:创建一个访问数据库的对象。
        第二步:使用第一步创建的数据库访问对象来执行transaction方法,通过此方法可以设置一个开启事务成功的事件响应方法,在事件响应方法中可以执行SQL.
        第三步:通过executeSql方法执行查询,当然查询可以是:CRUD。*/

    //Demo:获取或者创建一个数据库,如果数据库不存在那么创建之
    var dataBase = openDatabase("student", "1.0", "学生表", 1024 * 1024, function () {});
    /*	1,数据库名称。
        2,数据库的版本号,目前来说传个1.0就可以了,当然可以不填;
        3,对数据库的描述。
        4,设置分配的数据库的大小(单位是kb)。
        5,回调函数(可省略)。
        初次调用时创建数据库,以后就是建立连接了。
    (2)db.transaction方法可以设置一个回调函数,此函数可以接受一个参数就是我们开启的事务的对象。然后通过此对象可以进行执行Sql脚本,跟下面的步骤可以结合起来。
    (3)通过executeSql方法执行查询。
    ts.executeSql(sqlQuery,[value1,value2..],dataHandler,errorHandler)
    参数说明:
    sqlQuery:需要具体执行的sql语句,可以是create、select、update、delete;
    [value1,value2..]:sql语句中所有使用到的参数的数组,在executeSql方法中,将s>语句中所要使用的参数先用“?”代替,然后依次将这些参数组成数组放在第二个参数中
    ataHandler:执行成功是调用的回调函数,通过该函数可以获得查询结果集;
    4,errorHandler:执行失败时调用的回调函数;

    */
    window.onload = function () {//页面加载完成后绑定页面按钮的点击事件
        initDatabase();
        document.getElementById("btnSave").onclick = function () {
            var txtName = document.getElementById("txtName").value;
            var txtTitle = document.getElementById("txtTitle").value;
            var txtWords = document.getElementById("txtWords").value;
            console.log(txtName)
            console.log(txtTitle)
            console.log(txtWords)
            var db = getCurrentDb();
            //执行sql脚本,插入数据
            db.transaction(function (trans) {
                console.log(trans)
                console.log('insert')
                trans.executeSql("insert into Demo(uName,title,words) values(?,?,?) ", [txtName, txtTitle, txtWords], function (ts, data) {
                    console.log(ts);
                    console.log(data);
                });
            });
            showAllTheData();
        }
    }

    //初始化
    function initDatabase() {
        var db = getCurrentDb();//初始化数据库
        if (!db) {
            alert("您的浏览器不支持HTML5本地数据库");
            return;
        }
        db.transaction(function (trans) {//启动一个事务,并设置回调函数
            //执行创建表的Sql脚本
            trans.executeSql("create table if not exists Demo(uName text null,title text null,words text null)", [], function (trans, result) {
            }, function (trans, message) {//消息的回调函数alert(message);
                console.log(trans);
                console.log(message);
            }, function (trans, s) {//消息的回调函数alert(message);
                console.log(trans);
                console.log(s);
            });
        });
    }
    //连接数据库
    function getCurrentDb() {
        //打开数据库,或者直接连接数据库参数:数据库名称,版本,概述,大小
        //如果数据库不存在那么创建之
        var db = openDatabase("myDb", "1.0", "it's to save demo data!", 1024 * 1024);
        return db;
    }

    //显示所有数据库中的数据到页面上去
    function showAllTheData() {
        document.getElementById("tblData").innerHTML = '';
        var db = getCurrentDb();
        db.transaction(function (trans) {
            trans.executeSql("select * from Demo ", [], function (ts, data) {
                if (data) {
                    for (var i = 0; i < data.rows.length; i++) {
                        appendDataToTable(data.rows.item(i));//获取某行数据的json对象
                    }
                }
            },function(){
                console.log("error");
            });
        });
    }


    //删除Demo表
    function delAllTheData(){
        var db = getCurrentDb();
        db.transaction(function (trans) {
            console.log(trans)
            trans.executeSql("DROP TABLE Demo");
            location.reload();
        });
    }

    function appendDataToTable(data) {//将数据展示到表格里面
        //uName,title,words
        var txtName = data.uName;
        var txtTitle = data.title;
        var words = data.words;
        var strHtml = "";
        strHtml += "<tr>";
        strHtml += "<td>" + txtName + "</td>";
        strHtml += "<td>" + txtTitle + "</td>";
        strHtml += "<td>" + words + "</td>";
        strHtml += "</tr>";
        document.getElementById("tblData").insertAdjacentHTML('beforeEnd', strHtml);
    }
</script>
</body>
</html>

控制台打印图:

以上是我整理的html5三种本地存储知识,如需了解更多,自行百度。本地数据库的话,需要了解sql语句。 希望能帮到大家,大家有兴趣的话,可以加群:440279380,大家一起来分享前端知识。有什么疑问也可以直接留言。

发布者

cylyiou

cylyiou

分享前端知识

支付宝扫码打赏微信打赏

如果文章对您有帮助,不妨移至上方按钮小额赞助我一下,让我有动力继续写出高质量的教程。

发表评论

电子邮件地址不会被公开。