在使用 Pinia 进行状态管理时,常规方法难以直接持久化存储包含函数的对象。因为 JSON.stringify()在序列化对象时会忽略函数。本文将介绍一种自定义的解决方案,实现包含函数对象的持久化。
1. 安装依赖
确保项目中已经安装了 Pinia。如果没有安装,可以通过 npm 进行安装:
2. 自定义持久化逻辑
实现自定义的持久化逻辑,通过将函数序列化为字符串存储,在恢复时再转换回函数。
代码示例
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 54 55 56 57 58 59 60 61 62
| import { defineStore } from "pinia";
const loadState = () => { const state = localStorage.getItem("myStore"); if (state) { const parsedState = JSON.parse(state); if ( parsedState.myObject && typeof parsedState.myObject.sayHello === "string" ) { parsedState.myObject.sayHello = new Function( `return ${parsedState.myObject.sayHello}` )(); } return parsedState; } return null; };
const saveState = (state) => { const stateToSave = { ...state }; if ( stateToSave.myObject && typeof stateToSave.myObject.sayHello === "function" ) { stateToSave.myObject.sayHello = stateToSave.myObject.sayHello.toString(); } localStorage.setItem("myStore", JSON.stringify(stateToSave)); };
const myObjectWithFunction = { message: "Hello from Pinia!", sayHello: function () { console.log(this.message); }, };
export const useMyStore = defineStore("myStore", { state: () => { const savedState = loadState(); return ( savedState || { myObject: myObjectWithFunction, } ); }, actions: { updateMessage(newMessage) { this.myObject.message = newMessage; saveState(this.$state); }, }, onBeforeUpdate: () => { saveState(useMyStore().$state); }, });
|
3. 在组件中使用
在 Vue 3 组件中使用上述定义的 Pinia 存储。
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <template> <div> <button @click="callFunctionInObject">Call Function in Object</button> <input v-model="newMessage" placeholder="Enter new message" /> <button @click="updateMessage">Update Message</button> </div> </template>
<script setup> import { ref } from "vue"; import { useMyStore } from "./store";
const store = useMyStore(); const newMessage = ref("");
const callFunctionInObject = () => { store.myObject.sayHello(); };
const updateMessage = () => { store.updateMessage(newMessage.value); }; </script>
|
注意事项
- 安全风险:使用
new Function()存在安全风险,如果存储的函数字符串来自不可信源,可能会执行恶意代码。
- 复杂场景:函数序列化可能无法处理所有复杂情况,如函数内部引用了外部变量。
通过上述方法,我们能够在 Pinia 中实现包含函数对象的持久化存储,解决常规持久化方案无法处理函数的问题。