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响应到客户端
    cookie(失效,跨域,节流),session,操作localStorage增删查,vuex配合localStorage增删改_第1张图片

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的。
cookie(失效,跨域,节流),session,操作localStorage增删查,vuex配合localStorage增删改_第2张图片

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 = yyy   req.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重写)

cookie(失效,跨域,节流),session,操作localStorage增删查,vuex配合localStorage增删改_第3张图片

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的增删查功能

页面代码:

<input type="search"  id="search-input" placeholder="请输入你想比价的商品">
         <div class="search-history">
             <ul>
                 
             ul>
         div>
 <button id="search-btn">搜索button>   

操作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 = localStorage.getItem('searchHistory'); 
			if(!historyData) { 
				//因为一开始就没有这个searchHistory键名所以获取到为空,此时将historyData赋值为空数组
				historyData = [];
			}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 = JSON.parse(localStorage.getItem('searchHistory'));

		//循环遍历生成li标签
		var liHTML = "";
		for(var i=0;i<searchData.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 = 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 技术简介

    因为在实际操作中,vuex作为一个内存版的管理数据的仓库,当页面一刷新所有的数据都将变为初始值;所以我们可以将数据将存储在localStorage,我们vuex只管在初始化的时候或则数据变化的时候从localStorage获取数据就行了.

    5.2 案例

    整体需求:

    1. 就是其他组件改变了商品的数量,都要在我的根组件里面显示出来.

    技术实现:

    1. 因为涉及到多个组件的传值,如果用"prop down,event up"是远远不能满足需求,同时也会让逻辑更加复杂,所以用到了vuex来全局管理我们的购物车数量buycount
      cookie(失效,跨域,节流),session,操作localStorage增删查,vuex配合localStorage增删改_第4张图片
    2. 但是vuex的存储是内存版的,即页面重新加载后数据就会初始化;为了避免这个缺点,我们将所有的数据存到本地的localstorage中,vuex只需要做一个中间的桥梁
      cookie(失效,跨域,节流),session,操作localStorage增删查,vuex配合localStorage增删改_第5张图片

    具体业务代码:

    因为涉及到两个模块,所以我们抽取为不同的两个模块出来:

    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) //改
    

    你可能感兴趣的:(javaScript,后端,Vue)