nuxt.js + localStorage

使用 localStorage 进行缓存,操作比 cookie 更简单,且存储空间更大,用 vue.js 使用 localStorage 没什么问题,但是用 nuxt.js 使用 localStorage 就出现报错,因为服务端在寻找 localStorage,而其只存在于浏览器中。虽然使用 keep-alive 可以在页面跳转时,由于没有进行初始化实例的操作,所以数据还停留在页面,但是一旦刷新或者退出再进入页面,数据就不见了,所以只用 keep-alive 是远远不够的。

解决办法:

1、可以让客户端来初始化 Store,但会丧失服务端渲染的好处;

2、用 cookie 来替代 —— js-cookie

3、使用 nuxt-vuex-localStorage 插件;

我选择了第三种方式(点击使用资料),好处是:

1、不在服务端渲染;

2、可以使用 localStorage 也可以使用 sessionStorage;

3、加密;

4、可以设置过期时间;

5、操作简单,就像在正常使用 Store 目录中的文件。

我们知道 localStorage 是永久存储的,只能手动删除,我所想到的是在用户下一次进入页面时,判断时间的间隔判断删除与否,而使用这个插件可以很简单的设置过期时间;

如果要给存在 localStorage 中的数据加密的话,需要用到各种加密手段,并且其值只接受字符串类型,如果想存个数组或者对象,类型还需要转来转去,非常麻烦,而使用插件完全不需要考虑以上问题。

以下是使用这个插件过程中注意事项:

1、可以为每一个需要缓存的页面匹配一个 Store 文件,将这个匹配的文件注册到 modules 中:

module.exports = {
  modules: [
    ['nuxt-vuex-localstorage', {
      localStorage: ['foo', 'bar'],  //  If not entered, “localStorage” is the default value
      sessionStorage: ['sfoo', 'sbar']  //  If not entered, “sessionStorage” is the default value
    }]
  ]
}

其意思是:如果你有一个 foo.js 需要缓存到 localStorage,那么就像上面那样写,在为空的情况下,就默认为 localStorage.js

2、如果你要保存的值是数组或者对象,请创建一个副本,因为一旦你在单文件组件中改变了这个数组或者对象的数据,那么会报只能通过 Mutations 改变 state 中值的错误,由于数组和对象都是引用类型,所以必须创建一个副本才不会直接更改 state 中的值。

数组创建副本使用 newArr = oldArr.slice()

对象创建副本使用 newObj = Object.assign({},oldObj)

以上方式只能对第一层属性进行深克隆,如果希望完全深克隆,就使用递归方式

3、将数据或者对象写在另一个对象的外层,这样才能被访问到,具体什么原因,还不清楚(但是这么写的好处是,对象中的属性没有引用类型,所以可以只进行第一层属性的深克隆):

export const state = () => ({
  listNum: [],
  test: {
    imgAlt: '',
    imgSrc: '',
    titleCache: '',
    descCache: ''
  },
})

比如,listNum 一定要写在 test 对象外,否则无法访问到

4、使用 localStorage 时,要格外小心,如果陷入了死循环,需要直接打来浏览器的设置来清理缓存,否则页面无法打开

5、如果数据没有得到保存时,请查看存入缓存和取出缓存的顺序,有些操作是在 DOM 渲染之后才执行,有些是之前就已经执行了,比如以下这段代码:

add: async function (index,name) {
      this.count++
      this.items.splice(index+1, 0, { component: name, id: this.count })
      await this.$nextTick()
      $(".input_list")[index+1].focus()
      if(this.isNumMaker) {
        let len = this.$refs.list.length
        this.$refs.list[len-1].handleNumMaker()
      }
    }

await this.$nextTick() 之后的代码都需要等到 DOM 结构渲染完之后才会执行

6、将一个对象保存到 localStorage 时,出现,localStorage.js 中的值已经改变,但是没有同步到 localStorage 中,具体什么原因也不清楚,已经将问题在对应的 github.issue 中提出,有答案了再来回答。

我选择的替代方案是在单页面组件中直接使用 localStorate 来缓存部分数据,而能够正常显示,不过只要使用 localStorage 就一定要使用 try-cache,因为在某些浏览器用户关闭了本地存储功能或者使用隐身模式,有可能会导致浏览器直接抛出异常,代码就运行不下去。

如果要研究插件具体的实现可以在项目中 node_modules 中的 nuxt-vuex-localStoage 中查看,有疑问可以在对应的 gitub.issue 中提出,这个插件的制作者会在上面回答,没有比官方的教材更有效而直接的答案了。

编辑于 04-24