使用 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 中提出,这个插件的制作者会在上面回答,没有比官方的教材更有效而直接的答案了。