Jinuss's blog Jinuss's blog
首页
  • 源码合集

    • Leaflet源码分析
    • Openlayers源码合集
    • vue3源码
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

东流

Web、WebGIS技术博客
首页
  • 源码合集

    • Leaflet源码分析
    • Openlayers源码合集
    • vue3源码
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • 学习
  • 实用技巧
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • React

  • Vue

    • vue-demi介绍
    • 使用pinia-plugin-persistedstate如何清除localStorage中的数据
      • 概述
      • 问题介绍
        • 问题来源
        • 问题分析
        • 思考
      • 总结
    • script标签的setup实现原理
    • 前端中的拖拽知识
    • rollup-plugin-visualizer
  • JavaScript文章

  • 学习笔记

  • openlayers

  • threejs

  • MapboxGL

  • 工具

  • 源码合集

  • ECMAScript历年新特性

  • 前端
  • Vue
东流
2025-11-25
目录

使用pinia-plugin-persistedstate如何清除localStorage中的数据

# 概述

vue3前端项目,pinia是数据状态管理的官方标配,而pinia-plugin-persistedstate则是针对pinia库进行数据持久化的插件。

本文主要介绍在使用上述三个库(或插件)时,如何清除持久化后的数据。

# 问题介绍

# 问题来源

某个系统中userStore用于存放用户信息,并且使用了persist持久化用户信息userInfo。编写退出登录逻辑时,在userStore的退出action中重新赋值this.userInfo = {},并使用localStorage直接操作缓存,清除所有缓存数据。打开控制台发现localStorage并中依旧残存userInfo的缓存数据。

# 问题分析

this.userInfo的重新赋值,就是userStore的state发生了变化,这会触发pinia-plugin-persistedstate中的监听,在pinia-plugin-persistedstate中有如下代码:

store.$subscribe(
  (_mutation, state) => {
    persistState(state, persistence);
  },
  {
    detached: true
  }
);
1
2
3
4
5
6
7
8

如上代码会监听store中state的变化,继而触发persistState方法,而persistState的实现如下:

function persistState(state, { storage, serializer, key, paths, debug }) {
  try {
    const toStore = Array.isArray(paths) ? pick(state, paths) : state;
    storage.setItem(key, serializer.serialize(toStore));
  } catch (e) {
    if (debug)
      console.error("[pinia-plugin-persistedstate]", e);
  }
}
1
2
3
4
5
6
7
8
9

persistState会将需要持久化的state再次存储到storage中。

在pinia的源码中,store的订阅subscribe实现如下:

   $subscribe(callback, options = {}) {
            const removeSubscription = addSubscription(subscriptions, callback, options.detached, () => stopWatcher());
            const stopWatcher = scope.run(() => vueDemi.watch(() => pinia.state.value[$id], (state) => {
                if (options.flush === 'sync' ? isSyncListening : isListening) {
                    callback({
                        storeId: $id,
                        type: exports.MutationType.direct,
                        events: debuggerEvents,
                    }, state);
                }
            }, assign({}, $subscribeOptions, options)));
            return removeSubscription;
        }
1
2
3
4
5
6
7
8
9
10
11
12
13

store.$subscribe的第一个参数callback回调事件是通过vueDemi.watch监听某个具体的store变化,从而调用的。vueDemi.watch实际上就是vue中的watch方法。而watch方法默认是异步执行的。

即在userStore的action中执行this.userInfo = {},再清除缓存localStorage.clear(),会先改变userStore的state,此时会触发持久化库pinia-plugin-persistedstate中的监听,但是回调函数callback不会立即执行,而是会被放在异步队列中,等下一个事件循环中去执行,因此会先执行同步代码清除缓存localStorage.clear(),最后才是触发callback,在callback中拿到最新的state数据,调用persistState进行数据的再次持久化存储。

# 思考

pinia本身就是用于管理数据的,在实际开发中不提倡手动操作(缓存)数据,而且pinia提供了$reset方法会重置数据。因此可以封装一个统一的store管理工具。其实现如下:

// utils/storeManager.ts
import { useUserStore } from '@/stores/user'
import { useAppStore } from '@/stores/app'
import { useSettingsStore } from '@/stores/settings'

export class StoreManager {
  // 清除所有 store 的持久化数据
  static clearAllStores() {
    const stores = [
      useUserStore(),
      useAppStore(),
      useSettingsStore()
      // 添加其他需要清除的 store
    ]
    
    stores.forEach(store => {
      if (store.$reset) {
        store.$reset()
      }
    })
    
    // 可选:手动清除 localStorage 中的残留数据
    this.clearPersistedStorage()
  }
  
  // 清除特定的一组 store
  static clearStores(storeNames: string[]) {
    storeNames.forEach(name => {
      switch (name) {
        case 'user':
          useUserStore().$reset()
          break
        case 'app':
          useAppStore().$reset()
          break
        case 'settings':
          useSettingsStore().$reset()
          break
        // 添加其他 store
      }
    })
  }
  
  // 清除 localStorage 中的持久化数据
  private static clearPersistedStorage() {
    const prefix = 'your-app-name' // 你的应用前缀
    Object.keys(localStorage)
      .filter(key => key.includes('-store')) // 根据你的 key 模式过滤
      .forEach(key => {
        localStorage.removeItem(key)
      })
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

# 总结

引发问题的核心就是vue.watch的第二个参数回调函数是默认异步执行的,会造成localStorage.clear无法清除缓存的错觉。

编辑 (opens new window)
上次更新: 2025/11/25, 08:11:04
vue-demi介绍
script标签的setup实现原理

← vue-demi介绍 script标签的setup实现原理→

最近更新
01
patch中的双端比较快速算法
09-25
02
patchDOM元素的更新解析
09-25
03
patch中DOM元素的挂载解析
09-25
更多文章>
Theme by Vdoing | Copyright © 2024-2025 东流 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式