如何使用Vue的思想封装一个Storage

目录
  • 背景
  • 功能
  • 目的
  • 想法来源
  • 实现
    • set
    • get
    • deleteProperty
    • preventExtensions
    • has
  • 总结

背景

localStorage、sessionStorage 这两个 API 是我们前端日常开发中的存储的利器, 我们经常会使用它们存储一些数据。我们日常在对他们进行操作的时候,对 localStorage、sessionStorage 的使用一般是直接:

localStorage.setItem(xxx, xxx);
sessionStorage.setItem(xxx, xxx);
localStorage.getItem(xxx);
sessionStorage.getItem(xxx);

或者有的同学还会这样简单封装一下:

const getItem = (key) => {
   const serializedValue = window.localStorage.getItem(key) as any;
   return JSON.parse(serializedValue);
};
const setItem = (key, value) => {
  if (window && window.localStorage) {
    window.localStorage.setItem(key, JSON.stringify(value));
  }
};

但是这样使用起来虽然问题不大,但是总感觉代码不够优雅,正好最近封装了一些底层的基础库,就包括了对着两兄弟的封装。发现一些比较好玩的东西。小编也是有一些新的体会和想法,分享给大家。

功能

  • localStorage、sessionStorage 设置
  • localStorage、sessionStorage 获取
  • localStorage、sessionStorage 删除一项
  • localStorage、sessionStorage 清空所有存储

目的

封装一个 localStorage、sessionStorage API,实现对 storage 的增、删、改、查。

想法来源

大家如果使用过 Vue2.0 ,那你一定知道 Object.defineProperty 方法,这个 API 就是 Vue 响应式的核心,用于观测数据的变化,但是它存在一些弊端:

  • 对象类型数据里添加一对新的 key/value 或删除一对已有的 key/value 时,它是无法观测到的,导致当我们对 object 数据添加或删除值时,无法通知依赖,无法驱动视图进行响应式更新。
  • 对于数组变化侦测是 Vue2.0 通过拦截器实现的,也就是说只要是通过数组原型上的方法对数组进行操作就都可以侦测到,但是通过数组的下标来操作数据,就需要手动去操作了。

这些问题在 Vue 3.0 得到了解决,解决思路是 ES6 中的方法 Proxy 。

Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程。

Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。

Proxy 是一个天然的拦截器、代理器,所以我们也可以使用 Proxy 来代理对 localStorage、sessionStorage 的操作。话不多说,直接上代码。

实现

var proxyStorage = {
  /**
   * 返回 Storage 代理
   * @returns Proxy
   * @example
   * proxyStorage.getStorageProxy(localStorage, '_')
   */
  getStorageProxy: (storage, prefix) => {
    if (!storage)
      return false;
    const getKey = (prop) => `${prefix}.${String(prop)}`;
    return new Proxy(new Object(), {
      /**
       * 设置 storage
       * @returns boolean
       * @example
       * const storageProxy = proxyStorage.getStorageProxy(localStorage, '_');
       * storageProxy.a = 1;
       */
      set(target, prop, value) {
        target[prop] = value;
        storage.setItem(getKey(prop), JSON.stringify(value));
        return true;
      },
      /**
       * 获取 storage
       * @returns boolean
       * @example
       * const storageProxy = proxyStorage.getStorageProxy(localStorage, '_');
       * console.log(storageProxy.a);
       */
      get(_, prop) {
        return JSON.parse(storage.getItem(getKey(prop)) || '');
      },
      /**
       * 删除 storage
       * @returns boolean
       * @example
       * const storageProxy = proxyStorage.getStorageProxy(localStorage, '_');
       * delete storageProxy.a;
       */
      deleteProperty(_, prop) {
        storage.removeItem(getKey(prop));
        return true;
      },
      /**
       * 清空 storage
       * @returns boolean
       * @example
       * const storageProxy = proxyStorage.getStorageProxy(localStorage, '_');
       * Object.preventExtensions(storageProxy);
       */
      preventExtensions(target) {
        Object.preventExtensions(target);
        storage.clear();
        return true;
      },
      /**
       * 查询 storage
       * @returns boolean
       * @example
       * const storageProxy = proxyStorage.getStorageProxy(localStorage, '_');
       * 'a' in storageProxy;
       */
      has(target, prop) {
        try {
          return !!storage.key(prop);
        } catch (error) {
          return false;
        }
      }
    });
  },
};

var proxyStorageTest = proxyStorage.getStorageProxy(localStorage, '_');

利用 Proxy,返回一个 localStorage、sessionStorage 的代理对象,这个代理对象,对 set、get、delete、preventExtensions、in 等操作进行劫持。

set

拦截对象属性的设置,比如 storage.foo = v 或 storage['foo'] = v,返回一个布尔值。对代理对象的属性赋值,拦截这个赋值,操作对应的 storage 的 setItem,就可以直接把值存储到对应的 storage 中。

storage.a = 1;
// or
storage['a'] = 1;

get

拦截对象属性的读取,比如 storage.foo 和 storage['foo']。读取代理对象的属性值,拦截这个获取操作,拿到对应的 key,操作对应的 storage 的 getItem,从相应的 storage 中获取对应的值。

console.log(storage.a); // 1

deleteProperty

拦截 delete storage[propKey]的操作,返回一个布尔值。这里拦截的是对象的删除数据操作,内部对 storage 进行 removeItem 的操作,删除数据。

delete proxyStorageTest.a;

preventExtensions

拦截 Object.preventExtensions(storage),返回一个布尔值。拦截对象的不可扩展操作,内部对对应的 storage 进行 clear 操作,来清除所有的存储值。

Object.preventExtensions(proxyStorageTest);

has

拦截 propKey in proxy 的操作,以及对象的 hasOwnProperty 方法,返回一个布尔值。拦截对象的查询属性的操作,查询某一个 key 是否存在于对应的 storage 中。

'a' in proxyStorageTest;

总结

通过 Proxy 来代理对 localStorage、sessionStorage 的操作,封装一个 简单 storage API。Proxy 可用来操作 localStorage、sessionStorage ,也可用来操作 document.cookie 和 indexedDB。当然 Proxy 的功能并不局限于此,它也还有很多其他的用途,例如 Vue 3.0 中对 Proxy 的使用,亦或者其他,这篇文章重点不在于封装一个简单的 API,而是引导大家去学习这种思想。

到此这篇关于如何使用Vue的思想封装一个Storage的文章就介绍到这了,更多相关Vue思想封装Storage内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 如何使用Vue的思想封装一个Storage

    目录 背景 功能 目的 想法来源 实现 set get deleteProperty preventExtensions has 总结 背景 localStorage.sessionStorage 这两个 API 是我们前端日常开发中的存储的利器, 我们经常会使用它们存储一些数据.我们日常在对他们进行操作的时候,对 localStorage.sessionStorage 的使用一般是直接: localStorage.setItem(xxx, xxx); sessionStorage.setIte

  • vue element-ui之怎么封装一个自己的组件的详解

    为什么要进行组件封装? 封装的目的就是为了能够更加便捷.快速的进行业务功能的开发.组件(component)是vue的最强大功能之一,组件可以实现一些类似功能的复用及与其它业务逻辑的解耦.在开发中,我们难免会写很多类似的.重复的代码,有时候两个业务模块有相似的功能,采用复制粘贴已经很省事,但如果涉及的字段或有一些小差别,你也会觉得很烦,毕竟你要从头到尾瞅着去改动.这时候如果把那些相同的功能,抽象出来抽离成组件,通过组件引用方式就会显得格外省事了. Vue中怎么封装一个自己的组件 想要封装好一个组

  • Vue封装一个TodoList的案例与浏览器本地缓存的应用实现

    本文主要介绍了Vue封装一个TodoList的案例与浏览器本地缓存的应用实现,分享给大家,具体如下: 使用Vue封装一个简易的Todolist的小案例. 同时加入了浏览器本地缓存的技术手段. 浏览器本地缓冲: 前提: 一般我们定义的变量,或者用Vuex保存的数据, 当浏览器进行了一个刷新 那么这个数据就会丢失, 这样就做不出历史记录的效果了, 但是, 使用浏览器缓存就可以帮助我们解决这个问题- 浏览器缓存分为二种 sessionStorage 和 localStorage, 二种原型链分别如下:

  • Vue实现封装一个切片上传组件

    目录 组件效果 使用文档 封装过程 1. 文件切片 2. 构造切片请求参数 3. 控制分片请求的并发 完整代码 待完善 组件效果 单文件切片上传 多文件切片上传 组件使用案例 <template> <div id="app"> <div class="upload-wrap"> <UploadSlice :action="uploadInfoSlice.actionChunk" :headers=&quo

  • 第一个Vue插件从封装到发布

    前言 这是我封装的第一个Vue插件,实现的功能是滑动选择省市区,虽然只是一个简单的插件,但还是挺开心的,记录一下步骤. 插件地址:https://github.com/leichangchun/vue-area-select     欢迎指正 准备 Vue官网插件部分的介绍虽然很简单,但是还是好好刷一遍的.由于此插件较为简单,主要用到以下两个点: 1 . Vue的插件需要有一个公开方法install 2 . 通过全局方法 Vue.use() 使用插件,在下文有栗子 创建工程 初始化工程 vue

  • 手把手带你封装一个vue component第三方库

    为什么选择自己封装第三方库 最近几个月我司把之前两三年的所有业务都用了 vue 重构了一遍,前台使用 vue+ssr,后台使用了 vue+element,在此过程中封装和自己写了很多 vue component.其实vue 写 component 相当简单和方便,github上有很多的 vue component 都只是简单的包装了一些 jquery 或者原生 js 的插件,但我个人是不太喜欢使用这些第三方封装的.理由如下: 很多第三方封装的组件参数配置项其实是有缺损的.如一些富文本或者图表组件

  • 一篇文章带你使用Typescript封装一个Vue组件(简单易懂)

    一.搭建项目以及初始化配置 vue create ts_vue_btn 这里使用了vue CLI3自定义选择的服务,我选择了ts.stylus等工具.然后创建完项目之后,进入项目.使用快捷命令code .进入Vs code编辑器(如果没有code .,需要将编辑器的bin文件目录地址放到环境变量的path中).然后,我进入编辑器之后,进入设置工作区,随便设置一个参数,这里比如推荐设置字号,点下.这里是为了生成.vscode文件夹,里面有个json文件. 我们在开发项目的时候,项目文件夹内的文件很

  • Vue封装一个Tabbar组件 带组件路由跳转方式

    目录 Vue封装Tabbar组件 在App.vue 封装 路由跳转 利用router-view的特性 子组件Tabbar 然后就是配置的路由 从零开始封装一个Tabbar 首先底部菜单栏最外层是一个div, 代码如下 封装完每一个tabbaritem后 使用者在使用我们封装的控件时 Vue封装Tabbar组件 话不多说直接上代码 在App.vue 封装 路由跳转 利用router-view的特性 <template>   <div id="app">     &

  • vue封装一个图案手势锁组件

    目录 说在前面 效果展示 预览地址 实现步骤 1.组件设计 2.组件分析 3.组件实现 4.组件使用 组件库引用 源码地址 组件文档 说在前面 现在很多人都喜欢使用图案手势锁,这里我使用vue来封装了一个可以直接使用的组件,在这里记录一下这个组件的开发步骤. 效果展示 组件实现效果如下图: 预览地址 http://jyeontu.xyz/jvuewheel/#/JAppsLock 实现步骤 完成一个组件需要几步? 1.组件设计 首先我们应该要知道我们要做怎样的组件,具备怎样的功能,这样才可以开始

  • vue封装一个弹幕组件详解

    目录 前言 功能实现 1.获取随机颜色 随机数生成 随机颜色编码生成 2.随机生成弹幕出现的高度坐标 3.格式化弹幕对象 颜色 定位 4.创建弹幕对象 滚动动画定义 创建弹幕dom对象实例 弹幕销毁 弹幕循环 5.实时弹幕发送 html JavaScript 源码地址 前言 现在很多地方都有使用到弹幕,最近在捣鼓自己的个人博客网站,也想着在里面加入一个弹幕模块,所以在这里封装了一个可复用的弹幕组件,目前已经实现了基本的功能,可能还会有存在缺陷,后续会继续优化.这里给大家介绍分享一下实现的过程.

随机推荐