javaScript|cookie(失效,跨域,节流),session,操作localStorage增删查,vuex配合localStorage增删改

前言:
会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份.
一 什么是cookie
Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。
1.1 cookie的原理
一个cookie的设置以及发送过程分为以下四步:

  1. 客户端发送一个http请求到服务器端
  2. 服务器端发送一个http响应到客户端,其中包含Set-Cookie头部
  3. 客户端发送一个http请求到服务器端,其中包含Cookie头部
  4. 服务器端发送一个http响应到客户端
    javaScript|cookie(失效,跨域,节流),session,操作localStorage增删查,vuex配合localStorage增删改
    文章图片
1.2 操作cookie
cookie的常用属性:
// 1. expires 有效期 // 2. path 路径 // 3. domain 域名

1.2.1 服务器操作cookie
php操作cookie
// 设置cookie // setcookie(name, value, expire, path, domain); // 设置1小时后过期 setcookie("user", "lisi", time()+3600); // 获取单个cookie echo $_COOKIE["user"]; // 查看所有cookie print_r($_COOKIE);

1.2.2 (客服端)JS操作cookie
// 设置cookie function setCookie(key,value,param){ document.cookie = key + '=' + value + '; expires=' + param.expires + '; path=' + param.path; } // 获取cookie function getCookie(key){ var cookies = document.cookie; var arr = cookies.split('; '); if(arr){ for (var i = 0; i < arr.length; i++) { var kv = arr[i].split('='); if(kv[0] == key){ return kv[1]; } } } }

1.2.3 jQuery操作cookie
cookie插件基本使用 设置单个cookie 获取单个cookie 获取所有cookie 删除单个cookie 浏览器中cookie基本设置

1.3 cookie的节流
因为浏览器每次发送http请求的时候,都会带上cookie,这样如果浏览器请求的静态资源(图片等)也会带上cookie,那样会造成比较严重的带宽浪费.
解决办法:
1. 利用cdn实现请求静态资源是一个服务器,实现业务逻辑是一个服务器. 2. 严格控制cookie存放的有效,有用信息

1.4 cookie的跨域
二 什么是session
seesion是为了解决cookie安全问题的,把数据存入前端太危险,(数据存入服务端)
因为如果重要的数据都存在浏览器端,这样的数据容易泄露以及被修改,所以我们把原来存在cookie中部分数据存到服务器端.这种技术就叫session.
session可以理解为是服务器上的一个保险柜,把所有数据都保存在服务器的保险柜里,只给浏览器一把钥匙用来访问这些数据。数据都是存在服务器端,而浏览器端只存一把 钥匙。因为要把 钥匙给浏览器存起来,存钥匙的技术还是cookie,所以说session技术是基于cookie的。
javaScript|cookie(失效,跨域,节流),session,操作localStorage增删查,vuex配合localStorage增删改
文章图片

2.1 php操作session
1. php新增session
//一定要先调用此函数开启session session_start(); //通过超全局变量添加一条session记录 $_SESSION['名']= 值;

2. php删除session
// 开启session session_start(); // 删除保存的session // 删除变量的值 unset($_SESSION['name']);

3. php修改session
// 开启session session_start(); //修改 $_SESSION['name'] = 'rose';

4. php查询session
//一定要先调用此函数开启session session_start(); //直接通过超全局变量可以取到session记录 var_dump($_SESSION); //单独取出某条$_SESSION记录 echo $_SESSION['name'];

2.2 nodeJS操作session
const session = require('express-session') // 使用session的组件 // 集成session中间件req.session.xxx = yyyreq.session.xxx app.use(session({ secret: 'keyboard cat', resave: false, saveUninitialized: true })); app.get('/awesome', function(req, res){if(req.session.lastPage) { console.log('Last page was: ' + req.session.lastPage + "."); } req.session.lastPage = '/awesome'; res.send("You're Awesome. And the session expired time is: " + req.session.cookie.maxAge); });

三 cookie与session总结
session可以借助cookie实现状态维持,也可以不依赖cookie(URL重写)
javaScript|cookie(失效,跨域,节流),session,操作localStorage增删查,vuex配合localStorage增删改
文章图片

3.1 cookie的不可跨域性:
Cookie具有不可跨域名性。根据Cookie规范,浏览器访问Google只会携带Google的Cookie,而不会携带Baidu的Cookie。Google也只能操作Google的Cookie,而不能操作Baidu的Cookie。
Cookie在客户端是由浏览器来管理的。浏览器能够保证Google只会操作Google的Cookie而不会操作Baidu的Cookie,从而保证用户的隐私安全。浏览器判断一个网站是否能操作另一个网站Cookie的依据是域名。Google与Baidu的域名不一样,因此Google不能操作Baidu的Cookie。
需要注意的是,虽然网站images.google.com与网站www.google.com同属于Google,但是域名不一样,二者同样不能互相操作彼此的Cookie。而session对于整个网站都是有效的.
四 localStorage的优势
1、localStorage拓展了cookie的4K限制
2、localStorage会可以将第一次请求的数据直接存储到本地,这个相当于一个5M大小的针对于前端页面的数据库,相比于cookie可以节约带宽,但是这个却是只有在高版本的浏览器中才支持的
4.1 localStorage的局限
1、浏览器的大小不统一,并且在IE8以上的IE版本才支持localStorage这个属性
2、目前所有的浏览器中都会把localStorage的值类型限定为string类型,这个在对我们日常比较常见的JSON对象类型需要一些转换
3、localStorage在浏览器的隐私模式下面是不可读取的
4、localStorage本质上是对字符串的读取,如果存储内容多的话会消耗内存空间,会导致页面变卡
5、localStorage不能被爬虫抓取到
localStorage与sessionStorage的唯一一点区别就是localStorage属于永久性存储,而sessionStorage属于当会话结束的时候,sessionStorage中的键值对会被清空
4.2 实例:实现localStorage的增删查功能
页面代码:

    操作localStorage的JS代码
    var search = { //添加localstorage的方法 addlocalStorage :function () { var that = this; $('#search-btn').on('click',function(){var searchContent =$('#search-input').val(); //搜索框里的内容 //判断搜索框里的内容是否为空,如果为空不添加到localstorage不继续下面的操作 if(!searchContent) { //内容为空 return false; }//获取浏览器localstorage中键名为searchHistory中的数据 var historyData = https://www.it610.com/article/localStorage.getItem('searchHistory'); if(!historyData) { //因为一开始就没有这个searchHistory键名所以获取到为空,此时将historyData赋值为空数组 historyData = https://www.it610.com/article/[]; }else { //不为空,那么键名存在,数据也存在并且是字符串,现在转化为数组 historyData = JSON.parse(historyData); } //判断搜索的内容是否重复 if(historyData.indexOf(searchContent) != -1) { //如果有删除原来的内容,再作为第一个元素添加在数组前 historyData.splice(historyData.indexOf(searchContent),1); //删除 historyData.unshift(searchContent); //添加 }else { //如果没有,直接作为第一个元素添加在数组前 historyData.unshift(searchContent); } //将数据添加到键名为searchHistory中localstorage中的数据,不过又要把数组转成字符串 localStorage.setItem('searchHistory',JSON.stringify(historyData)); //调用查询历史记录的方法 that.queryHistory(); //在这里调用的意思是我搜索后就渲染到页面,可以不加 //清空下拉框里面的数据 $('#search-input').val(""); }); }, //查询localstorage的方法 queryLocalStorage : function(){ //先取出来 var searchData = https://www.it610.com/article/JSON.parse(localStorage.getItem('searchHistory')); //循环遍历生成li标签 var liHTML = ""; for(var i=0; i.length; i++) { //searchData里面有没有数据 if(searchData[i]) { var str = '
  • '+ searchData[i] +'
  • '; liHTML += str; } } //在页面上的操作渲染li //doSometing....... //给输入框一个成为焦点事件 $('#search-input').on('focus',function(){ $('.search-history ul').html(liHTML); //再给li一个点击事件 $('.search-history ul li').on('click',function(){ $('#search-input').val($(this).text()); $('.search-history ul').hide(); }); }); }, //删除历史记录 deleteHistory : function () {var that = this; $('.content ul').on('tap','i',function() {//获取被点击的索引id var index = $(this).data('id'); //获取当前本地存储的数组 把当前索引的值删掉 var historyData = https://www.it610.com/article/JSON.parse(localStorage.getItem('historyData')) || []; historyData.splice(index, 1); //删除完成后存储到本地存储中 把数组转成字符串 localStorage.setItem('historyData', JSON.stringify(historyData)); //查询新的历史记录 that.queryHistory(); }); },//清空历史记录 clearHistory : function () { var that = this; $('.clearTrash').on('tap',function(){ //2. 调用本地存储removeItem 删除某个键和值 localStorage.removeItem('historyData'); // 3. 在清空完成后调用查询刷新页面 that.queryHistory(); }); } }//调用添加localstorage的方法 search.addlocalStorage(); //调用查询localstorage的方法并渲染到页面 search.queryLocalStorage(); //调用方法,删除历史记录 search.deleteHistory(); //调用方法,清空历史记录 search.clearHistory();

    五 vuex配合localStorage增删改
    5.1 技术简介
    【javaScript|cookie(失效,跨域,节流),session,操作localStorage增删查,vuex配合localStorage增删改】因为在实际操作中,vuex作为一个内存版的管理数据的仓库,当页面一刷新所有的数据都将变为初始值; 所以我们可以将数据将存储在localStorage,我们vuex只管在初始化的时候或则数据变化的时候从localStorage获取数据就行了.
    5.2 案例
    整体需求:
    1. 就是其他组件改变了商品的数量,都要在我的根组件里面显示出来.
    技术实现:
    1. 因为涉及到多个组件的传值,如果用"prop down,event up"是远远不能满足需求,同时也会让逻辑更加复杂,所以用到了vuex来全局管理我们的购物车数量buycount
      javaScript|cookie(失效,跨域,节流),session,操作localStorage增删查,vuex配合localStorage增删改
      文章图片
    2. 但是vuex的存储是内存版的,即页面重新加载后数据就会初始化; 为了避免这个缺点,我们将所有的数据存到本地的localstorage中,vuex只需要做一个中间的桥梁
      javaScript|cookie(失效,跨域,节流),session,操作localStorage增删查,vuex配合localStorage增删改
      文章图片
    具体业务代码:
    因为涉及到两个模块,所以我们抽取为不同的两个模块出来:
    1. localStorage.js : 操作localstorage的增删改模块
    2. store.js : 操作vuex的存入数据,读取数据的模块
    store.js模块
    //store.js模块 import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex)//按需引入操作LocalStorage的模块 import { addLocalStorageItem,totalBuyCount,updateLocalStorageItem,deleteLocalStorageItem } from "../common/localStorage.js"//创建一个仓库 const store = new Vuex.Store({ state : { buyCount : 0, //购物车商品总数 }, getters: { //获取仓库中的数据 getTotalGoodsNum(state){ /** 1) 因为页面一刷新,此时的state.buyCount重置为0,然而,localstorage中存储的购买商品的 总数据是存在的,所以需要假设:如果state.buyCount === 0先去查询localstorage中存储 的购买商品的总数据返回给他,此时view更新.2) 添加购物车被点击了,state.buyCount在mutations里面变化了,state.buyCount !== 0 此时直接返回state.buyCount当前的值. */ return state.buyCount === 0 ? totalBuyCount() : state.buyCount }, getWantVisitPath(state) { return state.wantVisitPath } }, mutations: { //存入数据到仓库 /** * 添加购物车信息 * @param {*} state * @param {*} goods 约定的载荷 * goods { goodsID : 91, count: 2 } */ addShopCart(state,addGoods){ //添加数据,将数据存入localstorage中,将更新后的数据返回 state.buyCount = addLocalStorageItem(addGoods); }, //更新购物车信息 updateShopCart(state,updateItemGoods){ //更新数据,将更新后的数据返回 state.buyCount = updateLocalStorageItem(updateItemGoods) }, //删除购物车数据 deleteShopCart(state,delGoodsId){ //删除数据,将删除后的数据返回 state.buyCount = deleteLocalStorageItem(delGoodsId) }, }, }); //导出仓库,在main.js里面注入 export default store

    localStorage.js模块
    //localStorage.js模块 const key = "GOODS"; /** *获取localstorage里面的值 { 90 : 3} * @param {*} key键名 */ const getLocalStorage = ( key = "GOODS" )=>{ return JSON.parse(localStorage.getItem(key) || '{}') }//获取总共的buycount const totalBuyCount = ()=>{const localGoods = getLocalStorage(key); //获取本地存储的数据 let totalCount = 0; for( var key in localGoods ) { //遍历本地储存的数据 //将后面的键值加起来 totalCount += localGoods[key]; } return totalCount }//增加记录 const addLocalStorageItem = goods => {//1. 从localstorage里面取出item值判断 const localGoods = getLocalStorage(key) //这里传值亦可以不传亦可以//2. 判断是否有这个item,有就在和面覆盖键值,没有就加上去 // goods { goodsID : 91, count: 2 } if(localGoods[goods.goodsID]) { //这里是利用[]来取对象的键值 //有,计算覆盖前面的item的键值 localGoods[goods.goodsID] += goods.count }else { //没有的话,就重新添加 localGoods[goods.goodsID] = goods.count }// 3.把对象转成字符串,覆盖保存回去 localStorage.setItem(key,JSON.stringify(localGoods))// 4.重新统计一下localStorage中最新的数量,返回 return totalBuyCount(); }; //更改记录 const updateLocalStorageItem = updateGoods => { // console.log(updateGoods) {goodsID: 88, count: 2}//1. 从localstorage里面取出item值 const localGoods = getLocalStorage(key) //这里传值亦可以不传亦可以//2. 更新对应的item的值 localGoods[updateGoods.goodsID] = updateGoods.count// 3.把对象转成字符串,覆盖保存回去 localStorage.setItem(key,JSON.stringify(localGoods))// 4.重新统计一下localStorage中最新的数量,返回 return totalBuyCount(); }; //删除记录 const deleteLocalStorageItem = delGoodsId => { //console.log(delGoods)//goodsID: 88//1. 从localstorage里面取出item值 const localGoods = getLocalStorage(key) //这里传值亦可以不传亦可以//console.log(localGoods.delGoodsId) 这种方法是错误的,因为不能直接点 //2. 删除对应的值 delete localGoods[delGoodsId]// 3.把对象转成字符串,覆盖保存回去 localStorage.setItem(key,JSON.stringify(localGoods))// 4.重新统计一下localStorage中最新的数量,返回 return totalBuyCount(); }export { addLocalStorageItem, totalBuyCount, getLocalStorage, //获取LocalStorage的数据 updateLocalStorageItem, deleteLocalStorageItem };

    其他组件获取buycount的操作
    this.$store.getters.getTotalGoodsNum

    组件提供增删改数据的操作
    this.$store.commit('addShopCart',addGoods) //增 this.$store.commit('deleteShopCart',id) //删 this.$store.commit('updateShopCart',goods) //改

      推荐阅读