服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服务器之家 - 编程语言 - JavaScript - vue.js - 我面试最喜欢问的开放题:如何严谨二次封装 localStorage?

我面试最喜欢问的开放题:如何严谨二次封装 localStorage?

2024-03-13 15:09前端之神 vue.js

最近我在面试中,喜欢问一道有关于 hooks 的开放问题:二次封装一个 loaclStorage 的 hooks 时,需要考虑哪些问题呢?

在很多公司中,内部都会封装一些适用于公司内部业务的方法库来提高整个团队的开发效率,比如:

  • 防抖节流
  • 懒加载、虚拟滚动
  • dom增删改查、移动、拖拽
  • 管理状态

而在 Vue3 项目中,这种方法库表现为:hooks库,市面上有很多优秀的库,比如:vueuse。

最近我在面试中,喜欢问一道有关于 hooks 的开放问题:二次封装一个 loaclStorage 的 hooks 时,需要考虑哪些问题呢?

其实这是一道很简单的题,只不过想考考面试者在做业务的时候,会不会考虑更多的边界情况~接下来说说我对这个问题的小小的理解(可能也不是很全面)。

我面试最喜欢问的开放题:如何严谨二次封装 localStorage?

注意命名,防止污染

比如我现在一个域名下有两个子项目:

  • A项目
  • B项目

且这两个项目都需要存储 userInfo,那要怎么防止这两组数据互相污染呢?所以需要注意命名,在存储的时候加上对应的项目名前缀,或者其他标识符,保证这组数据是唯一的

const PROJECT_NAME = 'test-project'
localStorage.setItem(
  `${PROJECT_NAME}_userInfo`,
  JSON.stringify({ name: 'lsx' })
)

注意版本,迭代防范

请看一个例子,假如我们存储一段信息,类型是 string

// 存数据
const set = () => {
  const info = get()
  if (!info) {
    localStorage.setItem(
      `${PROJECT_NAME}_info`,
      'info_string'
    )
  }
}

// 取数据
const get = () => {
  const info = localStorage.getItem(
    `${PROJECT_NAME}_info`
  )
  return info
}

然后项目上线了一段时间,但是这个时候,突然决定要换成 object 类型了,这时候对应的存取方法也变了

// 存数据
const set = () => {
  const info = get()
  if (!info) {
    localStorage.setItem(
      `${PROJECT_NAME}_info`,
      JSON.stringify({ name: 'lsx' })
    )
  }
}

// 取数据
const get = () => {
  const info = localStorage.getItem(
    `${PROJECT_NAME}_info`
  )
  return JSON.parse(info)
}

但是这样其实是有隐患的,因为项目已经上线了一段时间,有些用户已经存过这个数据了,且存的是 string 类型,但是新版本上线之后,取数据却用了 object 的方式去取数据,这就导致了JSON.parse(字符串)会报错,影响正常的业务逻辑~

所以最好是加一个版本号,或者做一下错误兼容,这样就能避免了~

const PROJECT_NAME = 'test-project'
// 每次升级时改变版本号,规则自己定
const VERSION = 1

// 存数据
localStorage.setItem(
  `${PROJECT_NAME}_userInfo_${VERSION}`,
  JSON.stringify({ name: 'lsx' })
)

// 取数据
localStorage.getItem(
  `${PROJECT_NAME}_userInfo_${VERSION}`
)

时效性,私密性

时效性,那就是给存进去的数据加一个时效,过了某个时间,这个数据就时效了,方法就是每次存数据进去的时候,加一个时间戳:

// 原来
localStorage.setItem(
  `${PROJECT_NAME}_userInfo`,
  JSON.stringify({ name: 'lsx' })
)

const TIME_OUT = 3 * 60 * 60 * 1000
// 加时间戳
localStorage.setItem(
  `${PROJECT_NAME}_userInfo`,
  JSON.stringify({
    data: { name: 'lsx' },
    // 记录当前时间
    time: new Date().getTime()
  })
)

// 取数据时判断时间戳
const get = () => {
  let info = localStorage.getItem(
    `${PROJECT_NAME}_userInfo_${VERSION}`
  )
  info = JSON.parse(info)
  const now = new Date().getTime()
  if (now - info.time >= TIME_OUT) {
    localStorage.removeItem(
      `${PROJECT_NAME}_userInfo_${VERSION}`
    )
    return null
  }
  return info
}

有一些数据我们不得不存在 localStorage 中,但是又不想被用户看到,这时候就需要进行加密了(加密规则自己定):

// 加密函数
const encrypt = (v) => {}
// 解密函数
const decrypt = (v) => {}

// 存数据
localStorage.setItem(
  `${PROJECT_NAME}_userInfo_${VERSION}`,
  // 加密
  encrypt(JSON.stringify({ name: 'lsx' }))
)

// 取数据 解密
decrypt(localStorage.getItem(
  `${PROJECT_NAME}_userInfo_${VERSION}`
))

兼容 SSR

SSR 就是服务端渲染,是在服务端运行代码,拼接成一个页面,发送到浏览器去展示出来,所以在服务端是使用不了 localStorage 的,因为不是浏览器环境,所以你像封装一个比较通用的 localStorage,得兼顾 SSR 的情况:

// 在 SSR 中使用对象替代 localStorage
const SSRStorage = {
  map: {},
  setItem(v) {
    this.map[key] = v
  },
  getItem(key) {
    return this.map[key]
  }
}
let storage = null
// 判断环境
if (!window) {
  storage = SSRStorage
} else {
  storage = window.localStorage
}

原文地址:https://mp.weixin.qq.com/s?__biz=Mzg2NjY2NTcyNg==&mid=2247493293&idx=2&sn=fa43d7d9e9bcf6508635c188657016f5

延伸 · 阅读

精彩推荐
  • vue.jsvue3 Teleport瞬间移动函数使用方法详解

    vue3 Teleport瞬间移动函数使用方法详解

    这篇文章主要为大家详细介绍了vue3 Teleport瞬间移动函数使用方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    柏特-Better8512022-02-12
  • vue.js为啥我放弃用 Pinia 和 Vuex 去做字典状态管理呢?

    为啥我放弃用 Pinia 和 Vuex 去做字典状态管理呢?

    如果我们的字典数据封装是基于Pinia或Vuex去封装的,那就耦合在一起了,万一以后项目用了其他的状态管理工具呢?那是不是我又得基于这个状态管理工具...

    前端之神8902024-01-15
  • vue.jsvue+elementui通用弹窗的实现(新增+编辑)

    vue+elementui通用弹窗的实现(新增+编辑)

    这篇文章主要介绍了vue+elementui通用弹窗的实现(新增+编辑),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋...

    yingmhd8872021-12-27
  • vue.jsVue路由vue-router详细讲解指南

    Vue路由vue-router详细讲解指南

    这篇文章主要介绍了Vue路由vue-router详细讲解指南,对vue-router感兴趣的同学,可以参考下...

    有梦想的咸鱼前端7042022-03-10
  • vue.jsvue element el-transfer增加拖拽功能

    vue element el-transfer增加拖拽功能

    这篇文章主要介绍了vue element el-transfer增加拖拽功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们...

    早饭君5952021-12-31
  • vue.js如何以拖拽方式生成Vue用户界面

    如何以拖拽方式生成Vue用户界面

    这篇文章主要给大家介绍了关于如何以拖拽方式生成Vue用户界面的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学...

    白菜园10112022-02-23
  • vue.jsVue router-view和router-link的实现原理

    Vue router-view和router-link的实现原理

    这篇文章主要介绍了Vue router-view和router-link的实现原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友...

    mengyuhang48794492022-02-13
  • vue.js如何在vue中使用HTML 5 拖放API

    如何在vue中使用HTML 5 拖放API

    这篇文章主要介绍了如何在vue中使用HTML 5 拖放API,帮助大家更好的理解和使用vue框架,感兴趣的朋友可以了解下...

    疯狂的技术宅11802021-12-31