详解HTML5 LocalStorage 本地存储

1.前言

HTML5 storage提供了一种方式让网站能够把信息存储到你本地的计算机上,并再以后需要的时候进行获取。这个概念和cookie相似,区别是它是为了更大容量存储设计的。Cookie的大小是受限的,并且每次你请求一个新的页面的时候cookie都会被发送过去。HTML5的storage是存储在你的计算机上,网站在页面加载完毕后可以通过Javascript来获取这些数据。首先自然是检测浏览器是否支持本地存储。在HTML5中,本地存储是一个window的属性包括localStorage和sessionStorage,从名字应该可以很清楚的辨认二者的区别,前者是一直存在本地的,后者只是伴随着session,窗口一旦关闭就没了。二者用法完全相同,这里以localStorage为例。

rush:js;toolbar:false">if(window.localStorage){
 alert('支持localStorage');
}else{
 alert('不支持localStorage');
}

2.基本用法

存储数据的方法就是直接给window.localStorage添加一个属性,例如:window.localStorage.a 或者 window.localStorage["a"]。它的读取、写、删除操作方法很简单,是以键值对的方式存在的,如下:

rush:js;toolbar:false">localStorage.name = "kobi";//设置name为"kobi"
localStorage["name"] = "koko";//设置name为"koko",覆盖上面的值
localStorage.setItem("age","18");//设置age为"18"
var a1 = localStorage["name"];//获取name的值
var a2 = localStorage.age;//获取age的值
var b = localStorage.getItem("name");//获取name的值
localStorage.removeItem("c");//清除c的值

这里最推荐使用的自然是getItem()和setItem(),清除键值对使用removeItem()。如果希望一次性清除所有的键值对,可以使用clear()。另外,HTML5还提供了一个key()方法,可以在不知道有哪些键值的时候使用,如下:

rush:js;toolbar:false">var storage = window.localStorage;
function showStorage(){
 for(var i=0;i方法获得对应的值
document.write(storage.key(i)+ " : " + storage.getItem(storage.key(i)) + "
");  } }

 3.业务需求

表单实时保存数据,下次打开则提示是否继续编辑。图片等控件不支持,只支持简单的控件。【防止突然断电或浏览器崩溃时,下次打开还可以继续编辑并保存】。这样自然而然就想到了HTML5的本地存储功能。既然js写的烂,写的差,就当练手了。

其实这些数据的保存很简单,无非就是一些简单的标签数据的保存。先来一个最简单的js版本。

rush:js;toolbar:false">/**
 * 功能:保存用户修改完form标签内容在LocalStorage中。
 * 作者:黄金锋 
 * 版本:version 2.0
 */
define(function () {
//从localStorage中加载数据
function onload(form) {
var fh = form_handler;
var p = fh.getParams(form);
if (!p.bimId || !p.formId || !p.iid) {
return;
}
var id = 'FORM_' + DCI.LoginUser.UserId + '_' + p.bimId + '_' + p.formId + '_' + p.iid;
//alert(id);
var formDataDb;
var allControl = $(form).find("input:text[name],textarea[name]");
//从本地取
var storage = localStorage.getItem(id);
if (storage != null) {
var myData = JSON.parse(storage);
allControl.each(function (i, e) {
var name = $(e).attr("name");
if (myData[name] != null) {
$(e).val(myData[name]);
$(e).change();
}
});
}
//绑定change事件
allControl.each(function (i, el) {
var name = $(el).attr('name');
if (name) {
$(el).on('change', function () {
onchange(this);
});
}
});
//保存修改的数据
function onchange(el) {
var storage = localStorage.getItem(id);
if (storage == null) {
formDataDb = new Object();
var key = $(el).attr("name");
var value = $(el).val();
formDataDb[key] = value;
localStorage.setItem(id, JSON.stringify(formDataDb));
} else {
var myData = JSON.parse(storage);
var key = $(el).attr("name");
var value = $(el).val();
myData[key] = value;
localStorage.setItem(id, JSON.stringify(myData));
}
}
};
//删除localStorage中的数据
function onsave(form) {
var fh = form_handler;
var p = fh.getParams(form);
var id = 'FORM_' + DCI.LoginUser.UserId + '_' + p.bimId + '_' + p.formId + '_' + p.iid;
localStorage.removeItem(id);
var allGrid = $(form).find(".form-table");
var formId = $(form).data("formid");
allGrid.each(function (index,element) {
var formName = $(element).find("input:hidden[data-formid]").attr("name");
var storageKey = "FORM_" + formId + "_" + formName;
localStorage.removeItem(storageKey);
});
}
return {
onload: onload,
onsave: onsave,
}
});

表单都是自动通过模版生成的,这里附上表单加载需要的form.js.

代码太长,这里就不直接贴出来了,大家自己下载下来看吧 点击这里下载

4.Grid控件的数据保存

Grid控件其实就是一个div,公司的一些页面表单都是动态生成的,表单上面的控件也是动态生成的,所有很多东西都是自己手写的。下面是Grid控件的结构。

rush:js;toolbar:false"> 
  
  
  
  
下面是完成Grid数据保存的js.
/**
 * 功能:保存用户修改完form标签内容在LocalStorage中。
 * 作者:黄金锋 (549387177@qq.com)
 * 日期:2015-11-111:14:01
 * 修改:2015-11-19 16:09:00
 * 版本:version 3.0
 */
define(function () {
//从localStorage中加载数据
function onload(form) {
var fh = form_handler;
var p = fh.getParams(form);
if (!p.bimId || !p.formId || !p.iid) {
return;
}
var id = 'FORM_' + DCI.LoginUser.UserId + '_' + p.bimId + '_' + p.formId + '_' + p.iid;
var formDataDb;
var allControl = $(form).find("input:text[name],textarea[name]");
//从本地取
var storage = localStorage.getItem(id);
if (storage != null)
{
if (confirm("是否加载缓存数据")) {
var myData = JSON.parse(storage);
allControl.each(function (i, e) {
var name = $(e).attr("name");
if (myData[name] != null) {
$(e).val(myData[name]);
$(e).change();
}
});
}
}
var allGrid = $(form).find(".form-table");
var formId = $(form).data("formid");
var formStorage= localStorage.getItem("FORM_" + formId + "_isGridData");
if (formStorage=="1")
{
if (confirm("是否加载Grid缓存数据"))
{
//给Grid控件赋值
allGrid.each(function (index, element) {
var formName = $(element).find("input:hidden[data-formid]").attr("name");
var ipt = $(element).find("input[name]");
var table = $(element).find("input:hidden[data-formid]").siblings(".form-table-body").find(".table-hover");
var storageKey = "FORM_" + formId + "_" + formName;
var data = localStorage.getItem(storageKey);
var myData = JSON.parse(data);
if (myData != null) {
alert(data);
var InsertTotal = myData["Total"]["InsertTotal"];
var DelTotal = myData["Total"]["DelTotal"];
var Updatetotal = myData["Total"]["Updatetotal"];
var trIIdindex = myData["trIIdindex"]["IID"];
if (InsertTotal > 0) {
for (var i = 0; i < InsertTotal; i++) {
var tr = $('');
td.addClass('form-table-edit');
}
else {
var index = $(el).data('index');
var type = $(el).data('type')
if (type == "RowNumber") {
var val = row_data["RowNumber"];
td.html(val);
}
if (type == "CheckBox") {
var val = row_data[index];
td.append('');
}
if (index && type != "CheckBox") {
td.html(row_data[index]);
}
}
if ($(el).attr('width') == '0')
td.addClass('hidden');
td.appendTo(tr);
});
//table.find("tbody").append(tr);
table.append(tr);
tr.data("insert", true);
ipt.change();
}
}
if (Updatetotal > 0) {
for (var i = 0; i < UpdateTotal; i++) {
var row_data = myData["Update"][i];
var trIID = row_data["trIID"];
var trIndex;
table.find("tr").each(function (idx, ele)
{
var iid = $(ele).find("td").eq(trIIDIndex).html();
if (iid == trIID) {
trIndex = idx;
}
});
var cells = table.find("tr").eq(trIndex);
table.find('colgroup col').each(function (idx, el)
{
var index = $(el).data('index');
if (index)
{
var td = cells.find("td").eq(idx);
var type = $(el).data('type');
var test =new Object();
 
var text = row_data[index];
if (type == 'CheckBox')
{
 
var ck = td.find('input[type="checkbox"]');
if (text == '1')
ck.prop('checked', true);
else
ck.prop('checked', false);
}
else
{
td.text(text);
}
}
});
cells.data("update", true);
ipt.change();
}
}
if (DelTotal > 0) {
for (var i = 0; i < DelTotal; i++) {
var row_data = myData["Del"][i];
var trIID = row_data["trIID"];
table.find("tr").each(function (idx,ele) {
var iid = $(ele).find("td").eq(trIIDIndex).html();
if ( iid== trIID)
{
$(this).css("display", "none");
$(this).data("delete", true);
ipt.change();
}
});

}
}

}
});
}
}
//绑定change事件
allControl.each(function (i, el) {
var name = $(el).attr('name');
if (name) {
$(el).on('change', function () {
onchange(this);
});
}
});
//保存修改的数据
function onchange(el) {
var storage = localStorage.getItem(id);
if (storage == null) {
formDataDb = new Object();
var key = $(el).attr("name");
var value = $(el).val();
formDataDb[key] = value;
localStorage.setItem(id, JSON.stringify(formDataDb));
} else {
var myData = JSON.parse(storage);
var key = $(el).attr("name");
var value = $(el).val();
myData[key] = value;
localStorage.setItem(id, JSON.stringify(myData));
}
}
};
//删除localStorage中的数据
function onsave(form) {
var fh = form_handler;
var p = fh.getParams(form);
var id = 'FORM_' + DCI.LoginUser.UserId + '_' + p.bimId + '_' + p.formId + '_' + p.iid;
localStorage.removeItem(id);
var allGrid = $(form).find(".form-table");
var formId = $(form).data("formid");
allGrid.each(function (index,element) {
var formName = $(element).find("input:hidden[data-formid]").attr("name");
var storageKey = "FORM_" + formId + "_" + formName;
localStorage.removeItem(storageKey);
});
localStorage.setItem("FORM_" + formId + "_isGridData", null);
}
function ongridadd(form, table, data, tr) {
var inputflag = table.closest("div .form-table").find("input:hidden[data-formid]")
var storageKey;
var formId = $(form).data("formid");;
localStorage.setItem("FORM_" + formId + "_isGridData", "1");
var RowNumber = table.find(".active").children().eq(1).html();
var trIIDIndex;
var trIID;
table.find("col").each(function (idx, ele) {
if ($(ele).data("index") == "IID") {
trIID = table.find(".active").children().eq(idx).html();
trIIDIndex = idx;
}
});
var InsertObj = { trIID: trIID, RowNumber: RowNumber };
var columnArr = table.children().find("[data-index]");
if (columnArr) {
columnArr.each(function (index, element) {
var flag = $(element).data("index");
InsertObj[flag] = data[flag];
}); 
}

if (inputflag && trIID)
{
storageKey = "FORM_" + formId + "_" + inputflag.attr("name");
//var mydata = "{'Insert':[{'trIID':'1','ID':'test','IID':'测试'},{'trIID':'2','ID':'test2','IID':'测试2'}],'Update':[{'trIID':'3','ID':'test3','IID':'测试3'},{'trIID':'4','ID':'test4','IID':'测试4'}],'Del':[{'trIID':'1'},{'trIID':'2'}]}";
var getLocalStorage = localStorage.getItem(storageKey);
if (getLocalStorage) {
var dataObj = JSON.parse(getLocalStorage);
var InsertTotal = dataObj["Total"]["InsertTotal"];
 
dataObj["Insert"][InsertTotal] = InsertObj;
dataObj["Total"]["InsertTotal"] = InsertTotal + 1;
localStorage.setItem(storageKey, JSON.stringify(dataObj));
} else
{
var mydata = { Total: { InsertTotal: 1, UpdateTotal: 0, DelTotal: 0 }, Insert: [InsertObj], Update: [], Del: [], Notes: { storageKey: storageKey }, trIIDIndex: { IID: trIIDIndex } };
localStorage.setItem(storageKey, JSON.stringify(mydata));
}
}
}
function ongridedit(form, table, data, tr) {
 
var inputflag = table.closest("div .form-table").find("input:hidden[data-formid]")
var formId = $(form).data("formid");
var storageKey = "FORM_" + formId + "_" + inputflag.attr("name");
localStorage.setItem("FORM_" + formId + "_isGridData", "1");
var mySourceData = {};
var trIIDIndex;
table.find("col").each(function (idx, ele)
{
var index = $(ele).data("index");
var type = $(ele).data("type");
if (index)
{
if (type == "CheckBox")
{
var val = table.find(".active").children().eq(idx).html();
var value =$(val).val();
mySourceData[index] = value;
}
else
{
if (index == "IID")
{
trIIDIndex = idx;
}
mySourceData[index] = table.find(".active").children().eq(idx).html();
}
}
});
var trIID = mySourceData["IID"];
var UpdateObj = { trIID: trIID };
$.extend(UpdateObj, mySourceData);
var getLocalStorage = localStorage.getItem(storageKey);
if (getLocalStorage)
{
var dataObj = JSON.parse(getLocalStorage);
var InsertTotal = dataObj["Total"]["InsertTotal"];
var UpdateTotal = dataObj["Total"]["UpdateTotal"];
if (InsertTotal > 0)//新增后在编辑
{
for (var i = 0; i < InsertTotal; i++) {
var row_data = dataObj["Insert"][i];
if (row_data["trIID"] == trIID) {
$.extend(dataObj["Insert"][i], UpdateObj);
}
}
}
if (UpdateTotal > 0)//编辑之后在编辑
{
for (var i = 0; i < UpdateTotal; i++) {
var row_data = dataObj["Update"][i];
if (row_data["trIID"] == trIID) {
$.extend(dataObj["Update"][i], UpdateObj);
}
}
}

var UpdateTotal = dataObj["Total"]["UpdateTotal"];
dataObj["Update"][UpdateTotal] = UpdateObj;
dataObj["Total"]["UpdateTotal"] = UpdateTotal + 1;

localStorage.setItem(storageKey, JSON.stringify(dataObj));
}
else
{
var mydata = { Total: { InsertTotal: 0, UpdateTotal: 1, DelTotal: 0 }, Insert: [], Update: [UpdateObj], Del: [], Notes: { storageKey: storageKey }, trIIDIndex: { IID: trIIDIndex } };
localStorage.setItem(storageKey, JSON.stringify(mydata));
}
var testdata = localStorage.getItem(storageKey);
var myData = JSON.parse(testdata);
if (testdata != null) {
alert(testdata);
//alert(mydata);
//alert(myData["Total"]["InsertTotal"]);
//alert(myData["Insert"][0]["ID"]);
}
}
function ongriddel(form, table, tr) {
var inputflag = table.closest("div .form-table").find("input:hidden[data-formid]")
var formId = $(form).data("formid");
var storageKey = "FORM_" + formId + "_" + inputflag.attr("name");;
localStorage.setItem("FORM_" + formId + "_isGridData", "1");
var trIIDIndex;
var trIID;
table.find("col").each(function (idx, ele) {
if ($(ele).data("index") == "IID")
{
trIIDIndex = idx;
trIID = tr.find("td").eq(idx).html();
}
});
var DelObj = { trIID: trIID };
var getLocalStorage = localStorage.getItem(storageKey);
if (getLocalStorage) {
var dataObj = JSON.parse(getLocalStorage);
var isInsertData = false;
var isUpdateDel = false;
var InsertTotal = dataObj["Total"]["InsertTotal"];
var DelTotal = dataObj["Total"]["DelTotal"];
var UpdateTotal = dataObj["Total"]["UpdateTotal"];

if (InsertTotal > 0) {
for (var i = 0; i < InsertTotal; i++) {
var row_data = dataObj["Insert"][i];
if (row_data["trIID"] == trIID) {
isInsertData = true;
dataObj["Insert"][i] = null;
}
}
}
if (UpdateTotal>0)
{
for (var i = 0; i < Updatetotal; i++) {
var row_data = dataObj["Update"][i];
if (row_data["trIID"] == trIID) {
isUpdateDel = true;
dataObj["Update"][i] = null;
}
}
}
if (isInsertData)
{
var tempArr = [];
for (var i = 0; i < InsertTotal; i++) {
if (dataObj["Insert"][i] != null) {
tempArr[i]=dataObj["Insert"][i];
}
}
dataObj["Insert"] = tempArr;
dataObj["Total"]["InsertTotal"] = InsertTotal - 1;
}
else
{
if (isUpdateDel)
{
var tempArr = [];
for (var i = 0; i < InsertTotal; i++) {
if (dataObj["Update"][i] != null) {
tempArr[i] = dataObj["Update"][i];
}
}
dataObj["Update"] = tempArr;
dataObj["Total"]["Updatetotal"] = Updatetotal - 1;
} 

dataObj["Del"][DelTotal] = DelObj;
dataObj["Total"]["DelTotal"] = DelTotal + 1;

}
localStorage.setItem(storageKey, JSON.stringify(dataObj));
if (dataObj["Total"]["InsertTotal"] == 0 && dataObj["Total"]["Updatetotal"] == 0 && dataObj["Total"]["DelTotal"] == 0)
{
localStorage.setItem("FORM_" + formId + "_isGridData", null);
}
} else
{
var mydata = { Total: { InsertTotal: 0, Updatetotal: 0, DelTotal: 1 }, Insert: [], Update: [], Del: [DelObj], Notes: { storageKey: storageKey }, trIIdindex: { IID: trIIdindex } };
localStorage.setItem(storageKey, JSON.stringify(mydata));
}
}
return {
onload: onload,
onsave: onsave,
ongridadd: ongridadd,
ongridedit: ongridedit,
ongriddel: ongriddel
}
});

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程之家。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


我正在使用一个返回PNG编码的base64字符串的插件,我无法更改它,我必须使用它,但是我真正需要的是tiff编码值(base-64).有办法吗?我试图创建一个画布,加载pngbase64,然后使用toDataURL(‘image/tiff’),但经过一些研究,我发现不支持tiff作为toDataURL()的输出.有什么建议么?解决
我有这个正在玩的浏览器游戏.但是我也在尝试使其也可以在移动浏览器中使用.但是当同时按下多个按钮时,我似乎无法使其正常工作.我有这个游戏,您可以左右移动并跳跃.(见下图)touchbuttonsingamehttp://www.userhome.org/mobilegame.png我的代码如下所示:functioninittouc
我正在使用d3.js进行散点图绘制,我想绘制x和y轴以使其在点(100,75)相交.如何做到这一点?我在用svg.append("g").attr("class","axis").attr("transform","translate(0,"+(padding+223)+")").call(xAxis2);//CreateY2ax
我在htmlimg标签中有一张图片.我的要求是,当用户单击图像时,它将在拖动鼠标的同时标记一个点并画一条线.然后,当用户完成拖动并单击图像时,它应该显示的线条还以毫米/厘米为单位显示线条的尺寸.即,用户必须在图像上画一条线并显示其画线的距离/长度(以毫米/厘米为单位).如何在Web
我正在开发智能电视应用程序,并且从IP摄像机流媒体直播视频是该功能的很大一部分.相机手册指出,如果将其设置为流MPEG-4或H.264,则不支持HTTP.只有RTSP/RTP.替代方法(通过HTTP)是MotionJPEG,我希望尽可能避免这种情况(电视上的帧速率糟透了).是否有用于RTSP的JavaScript/HT
遵循ControlstartpositionanddurationofplayinHTML5video的原则,我尝试使每个片段播放完后自动将视频从一个片段跳到下一片段.每个片段的持续时间相同,每个片段的开始时间位于一个数组中.我似乎无法弄清楚如何在addEventListener之后循环遍历数组.varvideo=document
我正在尝试将相当简单的html导出到canvas,然后导出到png.为此,我正在使用rasterizeHTML(http://cburgmer.github.ioasterizeHTML.js/).我面临的问题是,我收到一条警告,例如正在加载外部图像/资源,但我没有.这是我尝试过的:HTML:<canvasheight="500"width="500"id="rasterize
Thisjsfiddledemonstratesthefollowingissue.最简单的示例是:<inputid="number"type="number"value="1">console.log(document.getElementById('number').value);这将按预期记录1.但是,这:<inputid="number"type
我正在使用Spring表单,并且想使用Spring表单似乎不支持的HTML5‘required’属性.<form:inputpath="someinput"cssClass="required"/>我似乎做不到<form:inputpath="someinput"cssClass="required"required="required"/>因为Spring
我正在使用angularJS开发应用程序.我的应用程序要求将数据保存在本地.因此,我正在使用HTML5本地存储.HTML5本地存储的问题在于,当用户清除浏览数据时,所有数据都将丢失,我们需要避免这种情况.我意识到,由于数据存储在用户计算机上,因此无法100%保护数据.本质上,是否有一种方法可以
我希望在首次加载时在我的网站上预加载一些小视频文件.这样,当用户单击以进入网站的一部分时,可以自动播放和使用它们.我需要无缝过渡,因此理想情况下应预加载整个视频文件,以免造成任何延迟.香港专业教育学院尝试了一些不同的插件,如html5preloader,以及其他一些JS技术将视频文件
 指引表单在网页应用中十分重要,基本上任何一个网站都必须使用到表单元素,所以表单的美观和易于交互对于网站设计就变得十分重要。HTML5对目前Web表单进行了全面提升,使得我们使用表单更加智能。它在保持了简单易用的特性的同时,还增加了许多内置的控件或者控件属性来满足用户的需
我正在学习JavaScript,但经验不足.但是我正在制作一个HTML表,我想在每个表单元格(<td>)中添加一个onClick事件.<tableid="1"><tr><tdonClick="tes()">1<d><tdonClick="tes()">2<d><r><tr
我正在使用AngularJS,并且在选择数据列表(html5)的元素时要使用指令ng-click.这是我的实际代码示例:<label>Search</label><inputtype="text"class="input-search"list="datalistcit"ng-change="changeQuery(queryCity)"ng-model="queryC
当您将来自其他域的图像放在画布中时,画布会受到污染,并且诸如getDataURL或getImageData之类的某些功能会被禁用.当您尝试使用此类功能时,会发生SECURITY_ERROR错误.为什么有这种保护措施?这种方法使用了哪种攻击?谢谢!编辑:我应该问:如何将来自其他域的图像用于攻击?   我弄不
我写了这个webRTC应用程序,它使用添加了不同滤镜的照片进行拍摄.当我单击“单击”按钮时,来自webRTC视频提要的帧将被加载到右侧的画布上.HTML代码-<videoid="vid"autoplay="true"></video><canvasid="cvs"></canvas><buttonid="btn1"onclick="start(
如果Chrome中使用了网络摄像头,则该页面的标签上会出现一个红点.并且,如果其他页面尝试访问网络摄像头,视频将变黑.我的问题是,是否可以使用JavaScript检查是否正在使用网络摄像头?怎么样?通过使用navigator.getUserMedia,我尝试了以下代码:navigator.getUserMedia=navigator.get
好的,所以我发现使用JqueryMobile和Phonegap开发androidApp在android4中工作正常,但是在旧版本(例如2.2.2)上,可滚动功能中断.因此,我尝试使用iScroll,但是存在冲突的问题,最终我只是决定编写一个Javascript函数来处理它.它曾经可以工作,但是现在坏了.所以这里是:<!DOCTYPEHT
我有一个正在构建的Webapp,并且刚开始使用SQLite.我已经能够创建表单,打开我创建的数据库,创建表和所需的字段以及在字段中输入数据.现在,我尝试使用SELECT语句读回数据,以将其显示在屏幕上以及列的列表中.我只是不知道javascript或HTML5中的SELECTstatemnt的语法‘SELECT*FRO
这些是我正在开发的表单的屏幕截图.我要设计表单中的选择框,以使选项中的文本右对齐,并且在选择选项后,所显示的所选文本也应显示如下图所示.HTML代码:<select><optionvalue="0"selected="selected"style="text-align:right;">EqualsTo</option><optionvalue="1&quo