首页 > 云开发 > JavaScript > 正文

后台-系统设置-扩展变量-手机广告位-内容正文顶部

浏览器存储

JavaScript

客户端的存储相当于给浏览器赋予了记忆功能。同一个站点的数据是如何共享数据的,一个页面填写的表单如何显示在另一个页面中,页面关闭或浏览器退出,打开还能重新显示原来的页面,这些都可以依靠浏览器的存储功能来实现。

一、Web存储 1、localStorage和sessionStorage

基本代码实现

两个属性都代表同一个Storage对象,一个持久化关联数组,数组使用字符串来索引,储存的值也是字符串的形式。localStorage和sessionStorage的区别在于储存的有效期和作用域不同,储存形式和api是一样的。

一般使用形式

localStorage.name = '曾田生'; // 储存字符串
var name = localStorage.name; // 获取存储信息

当储存数字时会自动转化成字符串,所以在取值是需要手动转换

localStorage.age = 666;
var age = parseInt(localStorage.age);

日期也一样

localStorage.time = (new Date()).toUTCString();
var time = new Date(Date.parse(localStorage.time));

咱们常用的json数据

localStorage.jsonData = JSON.stringify(data);
var jsonData = JSON.parse(localStorage.jsonData);

存储API

localStorage和sessionStorage除了可以通过上面的设置属性来存储值和通过查询属性来取值外,还有一套API操作数据。
下面就一个简单例子来说明:

// 存取值
localStorage.setItem('name','曾田生');
var name = localStorage.getItem('name');
// 获取 key - value 
var keyName = localStorage.key(0);
var value = localStorage.getItem(keyName);
// 删除指定值
localStorage.removeItem('name');
// 清空 localStora
localStorage.clear();

存储事件

localStorage和sessionStorage 存储发生变化就会触发存储事件,事件采用广播的机制,会在同样站点的作用域范围内发送消息。注意的是 localStorage和sessionStorage 的区别在于作用域的不同,所以事件触发的窗口也有区别,作用域在下面小节会讲到,还有一点是在发生存储数据改变的窗口上是不会触发该存储事件的。

下面一个小例子:
我打开了两个页面 index.html

btn.addEventListener('click', function () {
        localStorage.name = '曾田生'; // 储存字符串
        var name = localStorage.name; // 获取存储信息
    })

index2.html 做存储事件监听:window.addEventListener

window.addEventListener("storage", function(e){
        console.log(e);
        console.log("oldValue: "+ e.oldValue + " newValue:" + e.newValue);

    });

点击 index.html 的 button 后 index2.html打印出如下消息

存储有效期和作用域

localStorage和sessionStorage 的使用和api是相同的,但它们的有效期和作用域是有区别的。

(1)、localStorage
localStorage 的作用域限定在文档源级别,什么意思呢,协议、主机名、端口三者一样那就是同一文档源,同源的文档间共享同样的localStorage数据。比如如下:

http://www.example.com   // 协议:http;主机名:www.example.com
https://www.example.com     // 不同协议
http://demo.example.com     // 不同 主机名
http://www.example.com:8000 // 不同端口

以上只有不满足同源要求,即使在同一台服务器也不能共享localStorage数据。

(2)、sessionStorage
首先 sessionStorage的作用域也是限定在同源里面,并且sessionStorage的作用域还被限定在窗口中。
比如:
A.html

<a href="B.html">B.html</a>
<script type="text/javascript">
    sessionStorage.name = 'zengtiansheng'
    console.log(sessionStorage.name);
</script>

点击 A.html 的 <a 标签 能打开 B.html

<script type="text/javascript">
    console.log(sessionStorage.name);
    // 打印出 zengtiansheng
</script>

但是不通过 A.html 的 <a 标签 能打开 B.html ,而是直接打开 B.html 打印出的日志是 undefined

二、cookie

cookie最早是设计为被服务器所用,cookie数据会自动在web服务器和web浏览器之间传输的,所用服务器可读取来着客户端cookie的值并修改其cookie值。
或许你对自动传输这个概览不是很理解,先看一个例子:
设置cooike:

window.onload = function () {
    document.cookie = 'user = zss';
    document.cookie = 'age = 233';
}

接着想服务端随便发送一个GET请求:

app.get('/getAge', function (req, res) {
    console.log('-------------cookie---------');
    console.log(req.headers);
    console.log('-------------cookie---------');
    res.send('Hello World');
});

var server = app.listen(8081, function () {
    console.log("应用实例,访问地址为 http://%s:%s", host, port)
});

服务端接受GET请求咱们打印出响应头看看:

-------------cookie---------
{ host: '127.0.0.1:8081',
  connection: 'keep-alive',
  'upgrade-insecure-requests': '1',
  'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36',
  accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
  'accept-encoding': 'gzip, deflate, sdch, br',
  'accept-language': 'zh-CN,zh;q=0.8',
  cookie: 'Hm_lvt_800f0f35f4557a08958a37aa22f2d2b0=1485226901; user=zss; age=233',
  'if-none-match': 'W/"b-sQqNsWTgdUEFt6mb5y4/5Q"' }
-------------cookie---------

有没有看到虽然咱们客户端随便发送个请求,客户端就会把设置的 cookie 给带了过去,cookie数据会自动在web服务器和web浏览器之间传输

1、保存和读取cookie

保存 cookie

设置cookie非常简单,只需将cookie属性设置为一个字符串形式的值。如

    document.cookie = 'name='+encodeURIComponent('曾田生');

为什么需要 encode值呢,因为cookie的 名/值 中的值是不允许包含分号、逗号和空白符的。所用一般在存值得使用会采取相应的 encode,同样读取值得使用也需要 decode 一下。
上面一简单 名/值 的形式储存cookie数据的有效期只在当前 Web 浏览器的会话内,一但用户关闭浏览器cookie数据就丢失。
所以还可以给 cookie 添加日期和一些其他信息,只需以逗号分开:

document.cookie = 'name='+encodeURIComponent('曾田生')+
                        ';max-age='+60*60+   // 设置有效期 60*60就是1小时有效
                        ';path='+'path'+     // 设置路径
                        ';domain='+'domain'+
                        ';secure='+'secure';

读取 cookie

读取cookie 其返回值是一个字符串,所以下面写个了方法将字符串的 cookie 转成对象的形式:

function getCookie(){
        var cookie = {};
        var all = document.cookie;
        if(all === ''){
            return cookie;
        }
        var list = all.split('; ');
        for(var i= 0,len=list.length;i<len;i++){
            var ck = list[i];
            var p = ck.indexOf('=');
            var name = ck.substring(0,p);
            var value = ck.substring(p+1);
            value = decodeURIComponent(value);
            cookie[name] = value;
        }
        return cookie;
    }
2、cookie 的作用域

cookie的作用域是通过文档源和文档路径来确定的。该作用域是通过文档源和文档路径来确定,也可通过cookie的 path和domain属性来配置不同的作用域。

默认情况

默认情况下在下面页面创建了cookie,那么该cooki对页面同目录或子目录是可见的,如下页面创建了cookie:

http://www.example.com/src/index.html

那么该cookie对下面的页面是可见的:

http://www.example.com/src/index2.html
http://www.example.com/src/A/index.html
http://www.example.com/src/B/C/index.html

对下面页面不可见:

http://www.example.com/index3.html
http://www.example.com/A/index.html

path 改变作用域

前面也讲了,默认情况下哪个页面创建了cookie,那么该cooki对页面同目录或子目录是可见的。那要是我们有个需求是:用户在这个页面添加的表单数据在整个网站都可以用(包括它的父级页面)。
那就需要利用 cookie的path 属性了,如:
cookie是在以下页面所创建的:

http://www.example.com/A/B/index.html

修改 path:

document.cookie ='path='+'/A';   // 设置路径

本来只能在 /B 或 /B 以下的目录能访问到cookie ,现在 是在 /A 即以下目录能访问cookie 了!

进一步修改path:

document.cookie ='path='+'/';   // 设置路径

现在是该cookie对任何 http://www.example.com 这台服务器可见了!

发现点:把cookie的 path 设为 '/' 等于前面所说的 localStorage 拥有相同的作用域了!

domain 修改作用域

还有一种需求是:一些业务需要,A.example.com 域下的服务器想要读取 B.example.com 域下的服务器设置的cooike值,那该怎么办呢,domain它说它能解决:

document.cookie ='path='+'/'   // 设置路径
                  +';domain='+'.example.com' // 设置domain

那么,cookie就能在 example.com 下的任何其他服务器可见了。

cooike 的 secure 属性

cookie 默认是以不安全的形式(通过普通的,不安全的 HTTP 链接)传递的。
设置 secure:

document.cookie ='secure='+true'   

那么 cookie 只能在 HTTPS 或其他安全协议链接的时候它才能传递。

三、离线Web储存

localStorage和sessionStorage 只是保存了 web应用程序相关的数据,要是我们想要保存比如图片、
css 、js等文件 ,是否能做到呢。

1、appcache

HTML5新增了‘应用程序缓存’,配合一份缓存清单,就可实现比如图片、css 、js等文件的缓存,甚至做到
离线web应用。
下面以一个例子讲述:
项目文件:

index.html: 在 <html 标签添加 app.appcache 配置文件

<!DOCTYPE html>
<html manifest="app.appcache">
<head>
    <meta charset="UTF-8">
    <title>appcache test</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
<div class="img-1"></div>
<img class="img-2" src="img/img_2.png" alt="img2">
<div class="text" id="text"></div>
<script src="index.js"></script>
</body>
</html>

其中 style.css

body{
    background: #eb5f6f;
}
.img-1{
    width: 100px;
    height: 100px;
    background: url("img/img_1.png") no-repeat;
    background-size: 100%;
}
.img-2{
    width: 100px;
    height: 100px;
}

index.js

window.onload = function () {
    document.getElementById('text').innerHTML='appcache 测试';
}

app.appcache 配置文件:

CACHE MANIFEST
# version 1.0.1

index.js
style.css
img/img_1.png
img/img_2.png


NETWORK:
*

FALLBACK:
./index.html ./404.html

第一次加载页面:

可以看到资源被缓存了

再次刷新页面:
NetWork这边的 size 显示 form disk cache ,并且咱们的网页,css js 和图片都是正常显示的,但这时是从磁盘上获取的文件,而不是网络上。

有了上面的例子,咱们来介绍介绍 app.appcache 配置文件:

CACHE MANIFEST

清单文件必须以 CACHE MANIFEST 开头,其余一行一个 url,指向相对 .appcache 路径的资源,上面也看到了,资源可以是 .css .js 图片或其他。

NETWORK

标识了URL的资源从不缓存

NETWORK:
*

则表示任何不在清单的资源,浏览器都从网络加载。

FALLBACK

这个标签底下每行都包含两个URL ,比如:

FALLBACK:
./index.html ./404.html

第一个Url 表示匹配到的资源不被缓存起来,会去网络加载,第二个Url表示当第一个Url从网络加载的资源出错,那就加载第二个Url的资源来显示。

2、j慎用 appcache

虽然看了上面 appcache 感觉挺不错的样子,但不幸的是官方已经不推荐使用,这一套缓存在实际项目中纯在很多缺陷,比如:

1、当缓存清单缓存了文件,文件有改动,但用户访问的资源还是从缓存中读取,必须修改 appcache缓存文件,当用户

再次访问网页的时候缓存文件采取从新从服务器拉去资源,但糟糕的是只是去服务端拉取资源而已,用户访问的还是原来的缓存,需要用户再次刷新页面才能从缓存中读取新的资源。

这也是为什么我在

CACHE MANIFEST
# version 1.0.1

加了个 version 的原因,因为你改的任何 appcache 都会触发清单文件重新去服务器拉取资源

2、如果更新的资源中有一个资源更新失败了,将导致全部更新失败,将用回上一版本的缓存。这更坑

3、manifest本身的编写要求比较严格,要注意换行跟路径文件名之类的问题。不然缓存将无效。

等等,所以慎用,慎用

总结:

介绍了几种浏览器存储方式,希望对你所有帮助,起码有个大概了解也是可以的,在实际工作开发中要针对合适的场景选择合适的存储方式。

文章来源:segmentfault,作者:曾田生z。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:william.shi#ucloud.cn(邮箱中#请改为@)进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
后台-系统设置-扩展变量-手机广告位-内容正文底部

推荐文章

热门标签

    热门文章 最新文章 文章云

站内导航

全站搜索