前言
我们经常将获取到的用户信息和token等不会经常变更的数据存到本地,那么我们该如何实现当数据变化的时候自动同步更新本地数据呢,这就涉及到了本次要讲的内容。
先看这么一段代码
很明显以下代码中当我们输入内容后userInfo会发生改变但是本地数据不会立即相应的变化
<script setup>
import { reactive, watch } from 'vue'
const userInfo = reactive({
username: 'xiaosong123',
nickname: 'xiaosong',
})
localStorage.setItem('username', 'xiaosong123')
</script>
<template>
<div>
<p>{{ userInfo.username }}</p>
<input type="text" v-model="userInfo.username" />
</div>
</template>
使用watchEffact
改造之后的代码。很显然当我们username
发生改变之后执行回调函数同时也就把本地数据同步更新了。至于为什么使用watchEffact
这是一个经典的问题就是它和watch
的区别,这里不做过多赘述可自行翻阅文档。
import { reactive, watchEffect } from 'vue'
const userInfo = reactive(JSON.parse(localStorage.getItem('userInfo')) || {})
watchEffect(() => {
localStorage.setItem('userInfo', JSON.stringify(userInfo))
})
封装成useStorage工具
很显然这个操作我们不止要给userInfo
进行响应式处理,还会用的到token
等一些数据上,那么我们封装成函数最好了。这里使用compositionAPI
的方式。新建util/storage.js,复制以下代码。
import { reactive, watchEffect } from 'vue'
export const useStorage = (name, value = {}) => {
// 初次本地没有存储相关数据的时候使用传递过来的value
const data = reactive(JSON.parse(localStorage.getItem(name)) || value)
watchEffect(() => {
localStorage.setItem(name, JSON.stringify(data))
})
return { data }
}
使用useStorage
我们直接调用这个函数,如果是第一次存储数据就在第二个参数上传递初始值,通常来说这个数据是后端返回的。使用解构赋值获取到data
,这个data
是响应式的可以直接使用。
<script setup>
import { useStorage } from '../../src/util/localStorage'
const { data } = useStorage('userInfo', { username: 'xiaosong123', nickname: 'xiaosong' })
</script>
<template>
<div>
<p>{{ data.username }}</p>
<input type="text" v-model="data.username" />
</div>
</template>
我们自己封装的 useStorage,算是把 localStorage 简单地变成了响应式对象,实现数据的更新和 localStorage 的同步。同理,我们还可以封装更多的类似 useStorage 函数的其他 use 类型的函数,把实际开发中你用到的任何数据或者浏览器属性,都封装成响应式数据,这样就可以极大地提高我们的开发效率。
UseVue工具包
Vue 社区中其实已经有一个类似的工具集合,也就是 VueUse,它把开发中常见的属性都封装成为响应式函数,比如我们今天写的这个useStorage
工具包里都有。具体怎么用大家可以看一下官方文档UseVue,轮子已经做好了就不需要自己手动封装了。