乐趣区

一次设置过期时间引发的思考

前言

开发过程少不了会遇到给某个状态设置过期时间的需求, 例如: 进入页面有个默认弹窗, 用户关闭之后在 1 小时之内再次打开不能再弹; 面对这样需求我们首先想到的是需要设置一个变量去控制弹窗的隐藏 (因为默认是开启的), 如何去保证这个变量的有效时间呢? 这里就涉及到数据的持久化, 前端数据持久化可以理解为客户端数据的持久化, 就是数据存储在本地; 我们马上就想到了 cookie,localStorage,sessionStorage 这些属性了 …
下面先来解决这个需求, 稍后继续再说一下他们区别

通过 cookie 设置过期时间

cookie 是以键值对的形式保存在浏览器本地的一段文本字符串(前提是浏览器未禁用 cookie), 各个 cookie 字段之间一般是以“;”分隔, 即 ”key=value;xxx=yyy” 的格式 …

js 操作 cookie 的方式是通过 window.cookie 来进行读写的; 其中 expires 字段是: 设置 cookie 的生存时间, 当设置了一个时间点后, 每次访问浏览器会用当前时间和 cookie 的 expries 做比对,如果过期 cookie 则会被删除, 这样我们可以通过判断是否存在 cookie 来关闭弹窗提示了;

代码展示

// 设置 cookie
const setCookie = (name, value, time) => {let currentTime = new Date().getTime();
  let expireTime = new Date(currentTime + time);
  document.cookie = name + "="+ value + ";expires=" + expireTime.toGMTString();}
// 获取 cookie
const getCookie = name => {
    let strCookie = document.cookie; 
    let arrCookie = strcookie.split(';'); 
    // 遍历匹配
    for (let i = 0; i < arrCookie.length; i++) {let temp = arrCookie[i].split('=');
        if (temp[0] === name) {return temp[1];
        }
    }
    return '';
}
// 进入页面时就判断是否存在设定 cookie 值, 没有就默认显示; 如果有就不显示弹窗; 
// 当我们点击关闭时设置 cookie 的过期时间, 这里的业务代码就不写了

通过 localStorage 来设置

思路基本差不多, 就是在设置的时候额外添加一个时间戳, 然后取出来与当前时间做比较, 下面就直接上代码了.

代码展示

// 判断数据类型
dataType = data => {return Object.prototype.toString.call(data).slice(8, -1);
};

// 封装我的 localStorge
const myLocalStorage = {
    /**
     * @desc 设置缓存 + 过期时间
     * @param {String} item
     * @param {any} value
     * @param {Number} expire
     */
    set(item, value, expire) {value = dataType(value) === 'Object' ? JSON.stringify(value) : value;
        if (expire) {value += '?expire=' + (this.getTime() + expire);
        }
        window.localStorage.setItem(item, value);
    },
    get(item) {let data = window.localStorage.getItem(item) || '';
        let expireIndex = data.indexOf('?expire=');
        let expireTime = data.substring(expireIndex);
        let value = data.substring(0, expireIndex > 0 ? expireIndex : data.length);

        if (expireTime) {expireTime = expireTime.substring(8);
            if (expireTime < this.getTime()) {
                // 过期...
                this.clear(item);
                return '';
            } else {
                // 未过期...
                return this.getValue(value);
            }
        }
    },
    clear(item) {window.localStorage.removeItem(item);
    },
    // 获取当前时间
    getTime() {return new Date().getTime();},
    // 获取数据
    getValue(value) {
        // 这里还不够严谨, 判断 json 为数组和对象
        if (value.includes('{') || value.includes('[')) {return JSON.parse(value);
        } else {return value;}
    },
};

// 业务代码
// ==================================
import {myLocalStorage} from "@/common/js/tool";

export default {data() {
    return {tips: ""};
  },
  created() {this.getTip();
  },
  methods: {closeTip() {
      this.tips = false;
      this.setTip();},
    setTip() {myLocalStorage.set("showTip", "24 hours later", 24*60*60*1000);
    },
    getTip() {this.tips = myLocalStorage.get("showTip") || "";
    }
  },
  computed: {isShowTip() {return this.tips === "";}
  }
};

说说 localStorage,cookie 和 sessionStorage

其实写这篇文章的目的主要想梳理一下自己对这几个特性的理解, 分别从作用域, 存储大小, 生命周期, 注意事项来说

window.cookie

1. 一般由服务端生成, 保存在浏览器端的一段字符串, 参与服务端通信, 会携带在请求头中;
  如果在浏览器端生成 Cookie,默认是关闭浏览器后失效
  服务端可以通过 request 修改, 客户端也可以通过 window.cookie 来修改
2. 作用域范围
    遵循同源策略; 注意 domain 参数的设置, 顶级域名下二级, 三级域名是可以实现 cookie 共享的
3. 大小
    一般为 4K 左右, 浏览器有个数限制 20
4. 生命周期
    设置 expires ; 根据具体需求时间设置

window.localStorage

1. 存储在浏览器本地的一段字符串, 不参与和服务端的通信
2. 作用域范围
    同样遵循同源策略, 同源站点可以在同一浏览器下进行读写操作
3. 大小
    5M 左右
4. 生命周期
    一直存在, 除非人为清除

window.sessionStorage

1. 也是存储在浏览器本地的一段字符串, 不参与和服务端的通信
2. 作用域范围
    同样遵循同源策略, 同源站点, 同一 tab 标签页可以在同一浏览器下进行读写操作;
    即: 只有同一浏览器、同一窗口的同源页面才能共享数据; 如果新开一个 tab 标签是不行的
3. 大小
    5M 左右
4. 生命周期
    与标签页同在; tab 标签关了, 则数据清除

退出移动版