一、cookie
定义
Cookie是一种客户端(浏览器)把用户信息以文件形式存储到本地硬盘或内存的技术,说白了就是一种浏览器技术,本身为document对象的属性。
操作cookie的API很早就已经定义并实现,但是,由于这些API并没有提供保存、读取、修改、删除的方法。所有对cookie的操作都是通过特殊格式的字符串,读写document对象的cookie属性来完成。
cookie是客户端与服务端进行会话使用的一个能够在浏览器本地化存储的技术。简言之,cookie是服务器端发给客户端的文本文件,但只能储存4kb的数据;目的是用于辨别用户身份,记录跟踪购物车的商品信息(如数量)、记录用户访问次数等。
cookie的内容主要包括:名字name,值value,过期时间expires,路径path和域domain。路径和域一起构成cookie的作用范围。
一般cookie储存在内存里,若设置了过期时间则储存在硬盘里,浏览器页面关闭也不会失效,直到设置的过期时间后才失效。
若不设置cookie的过期时间,则有效期为浏览器窗口的会话期间,关闭浏览器窗口就失效。
拓展:什么是expires?
expires是给一个资源设定一个过期时间,也就是说无需去服务端验证,直接通过浏览器自身确认是否过期即可,所以不会产生额外的流量。此种方法非常适合不经常变动的资源。如果文件变动较频繁,不要使用expires来缓存。
expires起到控制页面缓存的作用,合理的配置expires可以减少很多服务器的请求
原理:客户端请求服务器时,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。而客户端浏览器会把Cookie保存起来。当浏览器再请求服务器时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器通过检查该Cookie来获取用户状态。
由于所有新旧浏览器都支持cookie,所以仍然被客户端程序员大量使用.
//创建cookie
document.cookie = 'name=haha';
//如果要一次存储多个名/值对,使用分号加空格隔开
document.cookie = 'name=haha; password=123';
由于cookie的名或值中不允许包含分号、逗号、等号和空格,因此在存储前,可以使用Javascript的全局函数encodeComponent()对值进行编码。
document.cookie看上去像一个属性,可以赋不同的值。但它和一般的属性不同,重复给它赋值,原来的值并不会丢失,例如,连续执行下面两条语句:
document.cookie = "userId=Gates";
document.cookie = "password=123";
这时浏览器将维护两个cookie,分别是userId和password。可以看出,document.cookie其实是一个容器,给它赋值时,如果该名不存在,则会在容器中添加一个名/值对;如果该名存在,则会修改该名所对应的值。
下列为常用属性:
// document.cookie = 'name=value[;expires = 日期对象][;path = 路径][;domain = 域名][;secure(是否加密)]';
函数封装
项目有参考 js-cookie,一个简单的,轻量级的处理cookie的jsAPI(可直接在项目中安装使用)。也可自己封装cookie:
//======/src/lib/cookie.js======
/*!
* JavaScript Cookie v2.2.0
* https://github.com/js-cookie/js-cookie
*
* Copyright 2006, 2015 Klaus Hartl & Fagner Brack
* Released under the MIT license
*/
function myCookie() {
function extend() {
var i = 0;
var result = {};
for (; i < arguments.length; i++) {
var attributes = arguments[i];
for (var key in attributes) {
result[key] = attributes[key];
}
}
return result;
}
function init(converter) {
function api(key, value, attributes) {
if (typeof document === 'undefined') {
return;
}
// Write
if (arguments.length > 1) {
attributes = extend({
path: '/'
}, api.defaults, attributes);
if (typeof attributes.expires === 'number') {
attributes.expires = new Date(new Date() * 1 + attributes.expires * 864e+5);
}
// We're using "expires" because "max-age" is not supported by IE
attributes.expires = attributes.expires ? attributes.expires.toUTCString() : '';
if (Object.prototype.toString.call(value) == "[object Object]") {
try {
var result = JSON.stringify(value);
if (/^[\{\[]/.test(result)) {
value = result;
}
} catch (e) { }
}
value = converter.write ?
converter.write(value, key) :
encodeURIComponent(String(value))
.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
key = encodeURIComponent(String(key))
.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent)
.replace(/[\(\)]/g, escape);
var stringifiedAttributes = '';
for (var attributeName in attributes) {
if (!attributes[attributeName]) {
continue;
}
stringifiedAttributes += '; ' + attributeName;
if (attributes[attributeName] === true) {
continue;
}
// Considers RFC 6265 section 5.2:
// ...
// 3. If the remaining unparsed-attributes contains a %x3B (";")
// character:
// Consume the characters of the unparsed-attributes up to,
// not including, the first %x3B (";") character.
// ...
stringifiedAttributes += '=' + attributes[attributeName].split(';')[0];
}
return (document.cookie = key + '=' + value + stringifiedAttributes);
}
// Read
var jar = {};
var decode = function (s) {
return s.replace(/(%[0-9A-Z]{2})+/g, decodeURIComponent);
};
// To prevent the for loop in the first place assign an empty array
// in case there are no cookies at all.
var cookies = document.cookie ? document.cookie.split('; ') : [];
var i = 0;
for (; i < cookies.length; i++) {
var parts = cookies[i].split('=');
var cookie = parts.slice(1).join('=');
if (!this.json && cookie.charAt(0) === '"') {
cookie = cookie.slice(1, -1);
}
try {
var name = decode(parts[0]);
cookie = (converter.read || converter)(cookie, name) ||
decode(cookie);
if (this.json) {
try {
cookie = JSON.parse(cookie);
} catch (e) { }
}
jar[name] = cookie;
if (key === name) {
break;
}
} catch (e) { }
}
return key ? jar[key] : jar;
}
api.set = api;
api.get = function (key) {
return api.call(api, key);
};
api.getJSON = function () {
return api.apply({
json: true
}, arguments);
};
api.remove = function (key, attributes) {
api(key, '', extend(attributes, {
expires: -1
}));
};
api.defaults = {};
api.withConverter = init;
return api;
}
return init(function () { });
};
export default myCookie();
使用:
import iCookie from '@/lib/cookie.js'
let loginTimes = iCookie.get('login_times',{path:'/'})||0;
if(loginTimes!=0){
iCookie.remove('login_times',{path:'/'});
}
iCookie.set('login_times', loginTimes, { path: '/', expires: 0.0001 }); //10s
iCookie.set('serviceIslogin',false);
iCookie.get('serviceIslogin')
二、webStorage本地存储
localStorage 和 sessionStorage
web Storeage的概念和cookie很相似,
区别在于web Storage更够储存各多的数据,cookie的大小是受限的,
并且每次请求一个新的页面的时候都会被发送过去,无形中浪费了带宽,
另外cookie还需要指定作用域,不可跨越调用。
HTML5增加了两个储存方式:localStorage和sessionStorage
- 存储内容大小一般支持5MB左右(不同浏览器可能还不一样)
- 浏览器端通过
Window.sessionStorage和Window.localStorage属性来实现本地存储机制。 - 相关API:
xxxxxStorange.setItem('key','value'):该方法接受一个键和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应的值。xxxxxStorange.getItem('key'):该方法接受一个键名作为参数,返回键名对应的值。xxxxxStorange.romoveItem('key'):该方法接受一个键名作为参数,并把该键名对应的键值对从存储中删除。xxxxxStorange.clear(): 该方法会清空存储中的所有数据。
- 备注:
- SessionStorage存储的内容会随着浏览器窗口关闭而消失。
- LocalStorage存储的内容,需要手动清除才会消失。
xxxxxStorange.getItem('key')如果key对应的value获取不到,那么getItem的返回值是null。- 存进去的value值都会转成字符串,所以如果存储的value值是对象的话,用
JSON.stringfy(value)转成对象字符串,取的时候用JSON.parse(value)函数解析一下。 JSON.parse(null)的结果依然是null。
三、本地存储与cookie存储的区别
三者的特点:
- cookie:兼容性很好,可以灵活的设置数据的生命周期,缺点是操作不方便,需要大量的字符串处理
- localStorage:IE67 不认识,永久性存储,只要用户不删除或调用 clear 方法就永远 不会删,操作很方便
- sessionStorage:兼容性与 localStorage 一样,但是存储时间是会话(在当前标签页 无论跳转到该网站的哪一个页面都能获取到,但关闭浏览器就会销毁,并且在其他 标签页面中是获取不到的)
三者的区别
- cookie在浏览器和服务器间来回传递。而sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。
- cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下。存储大小限制也不同,cookie数据不能超过4kb,同时因为每次http请求都会携带cookie,所以cookie只适合保存很小的数据,如会话标识。sessionStorage和localStorage虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。
- 数据有效期不同。
- 作用域不同。sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;locakStorage在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。Web Storage 支持事件通知机制,可以将数据更新的通知发送给监听者。Web Storage 的 api接口使用更方便。