使用pinia
时经常有需要重置某个、或者某几个属性字段的需求,不过,pinia
的$reset
方法只支持重置整个state
,并不支持针对单个属性进行重置。
从这条issues回复中也可以看出pinia
后续并不打算支持,而是希望开发者通过拓展插件的方式来实现。通过官网可以看到plugins支持以下扩展操作:
- 向
Store
添加新属性 - 定义
Store
时添加新选项 - 为
Store
添加新方法 - 包装现有方法
- 更改甚至取消操作
- 实现本地存储等副作用
- 仅适用于特定
Store
借此需求正好可以熟悉以下pinia plugins
的开发使用
查看源码,了解到$reset
其实也是通过
p
a
t
c
h
来进行重置的,既然如此,只需要拓展一个
‘
patch来进行重置的,既然如此,只需要拓展一个`
patch来进行重置的,既然如此,只需要拓展一个‘resetFields方法,可以传入只希望重置的字段名称(不传也可以重置整个
state`)
当然还要考虑ts
的类型提示,那就可以简单的有如下实现
import { PiniaPluginContext } from "pinia";
import { pick } from "lodash-es";
declare module "pinia" {
// eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars
export interface _StoreWithState<Id extends string, S extends StateTree, G, A>
extends StoreProperties<Id> {
// 选择自定义一个方法名,当然,你也可以覆盖$reset方法,这里只是不想破坏原有的东西,仅为示例
$resetFields<K extends keyof S>(fields?: K[]): void;
}
}
export default ({ options, store }: PiniaPluginContext): void => {
store.$resetFields = (fields) => {
const { state } = options;
let originalState = state ? state() : {};
store.$patch(($state) => {
if (fields) {
originalState = pick(originalState, fields);
}
Object.assign($state, originalState);
});
};
};
然后在use
store
之前使用咱自定义的插件即可生效
下面是个简单的使用示例
import type { App } from "vue";
import { createPinia } from "pinia";
// 引入自定义插件
import piniaReset from "/@/plugins/pinia/piniaReset";
const store = createPinia();
// 使用插件
store.use(piniaReset);
app.use(store);
example.vue
import { useDemoStore } from "/@/store/modules/demo";
// 任意state都将具有$resetFields方法
const demoStore = useDemoStore();
demoStore.$resetFields(["count"]);