监听localStorage

1,644 阅读2分钟

前言

前几天在使用VueUse的时候,发现了一个神奇的api---useLocalStorage,它的作用简单来概括就是说,可以使localStoragevue3的响应式对象一样使用,举个栗子:

<script setup lang="ts">
import {useLocalStorage} from '@vueuse/core'

const ref = useLocalStorage('test',{a:1});

ref.value = {a:2}
</script>

用这段代码为例,在使用useLocalStorage创建了一个响应式对象后,再改变它的{a:2},它就会同步到本地的localStorage:

image.png

这个还是比较好理解的,实际上我们也可以自己使用ref去写一个,但是当我监听这个,并在面板中删除这个的时候,神奇的事情发生了。但是首先,让我们先添加watch监听这个

import {useLocalStorage} from '@vueuse/core'
import { watch } from 'vue';

const ref = useLocalStorage('test',{a:1});

ref.value = {a:2}

watch(ref,(val)=>{
  console.log(val);
})

然后在面板中尝试删除这个:

5.gif

可以发现,这个,首先被初始化为了初始值{a:1},之后,watch竟然被触发了。看到这里,我非常的不理解,因为我不理解面板的删除是如何触发watch的。所以只有看源码了。

查看源码

首先,我们克隆vueuse,这个

image.png

因为useLocalStorage其实调用的是useStorage,所以我们这里打开 packages\core\useStorage下的index.ts:

image.png

然后跳到170行,可以看到:

image.png

看到这里,就可以得出一个很明确的结论了:浏览器提供了storage的监听,那到底是不是这样呢,我们自己验证一下,在上面的代码基础上继续添加一行addeventListener:

<script setup lang="ts">
import {useLocalStorage} from '@vueuse/core'
import { watch } from 'vue';

const ref = useLocalStorage('test',{a:1});

ref.value = {a:2}

watch(ref,(val)=>{
  console.log(val);
})

window.addEventListener('storage',(ev)=>{
  console.log(ev.newValue)
})
</script>

然后重复删除操作,

5.gif 可以,看到删除动作被监听到了。

当然,如果你用typescript,其实在写事件的时候,就已经提示你storage这个事件image.png

结论

  1. 浏览器的window对象提供了storage的事件可以监听,storage的改变
  2. VueUseuseLocalStorage就是靠storage事件,来监听面板操作,来达到保持响应式的。