其实pinia使用state就够了
在pinia中使用state、getter、action中区划分数据和函数其实仍然是类似于option api的使用方式,这也导致了使用这种方式配合ts时类型支持仍然不够友好,也没有办法对store做组合(没办法得到正确的类型提示),但如果我们使用computed代替getter,并且action也放到state里面就可以做到了
封装基础store(封装大部分模块都要遇到的增删改查功能)
// store/basic.ts
import { computed, reactive, Ref, ref } from "vue";
import { http } from '@/http/http';
import { ElMessage } from "element-plus";
import { AxiosRequestConfig } from "axios";
export type AddConfig = boolean | undefined | (Partial<{
/**请求玩数据是否更新列表 */
$refresh: boolean,
}> & AxiosRequestConfig)
export type DeleteConfig = AddConfig;
const parseConfig = (config: AddConfig | DeleteConfig) => {
if(config === undefined || typeof config === 'boolean') {
return {
$refresh: !!config
}
} else {
return config;
}
}
export const useBasicStore = <DataType>(url: string = '') => {
/**模块列表数据 */
const list = ref([]) as Ref<DataType[]>;
const pageInfo = reactive({
page: 0,
page_size: 10,
total: 0,
})
/**模块详情数据 */
const data = ref(null) as Ref<DataType | null>;
/** 草稿数据 用于新增 */
const draftData = ref({}) as Ref<Partial<DataType>>;
/**列表激活模块 */
const current = ref(null) as Ref<DataType | null>;
/** 请求指示器 */
const pending = reactive({
get: false,
delete: false,
put: false,
post: false,
})
const isPending = computed(() => {
return Object.values(pending).some(v => v);
});
const onFetch = <T>(promise: T, key: keyof typeof pending): Promise<T> => {
pending[key] = true;
return Promise.resolve(promise).finally(() => pending[key] = false);
}
const getList = async(params:IHttp.BasicRequestListQuery = {}, config?: AxiosRequestConfig) => {
config = config || {};
const result = await onFetch(http.get<IHttp.BasicResponseList<DataType>>(url, { params, ...config }), 'get');
pageInfo.page = result.data.page;
pageInfo.page_size = result.data.pageSize;
pageInfo.total = result.data.totalPage;
list.value = result.data.data;
return list;
}
const getDetail = async (id: string | number, config?: AxiosRequestConfig) => {
config = config || {};
const result = await onFetch(http.get<DataType>(`${url}/${id}`, config), 'get');
data.value = result.data;
return data;
}
const update = async (id: string | number, payload: Partial<DataType>) => {
const result = await onFetch(http.put(`${url}/${id}`, payload), 'put');
ElMessage.success(`更新成功`);
return result.data;
}
const add = async (payload: Partial<DataType>, config: AddConfig) => {
config = parseConfig(config);
const result = await onFetch(http.post(`${url}`, payload, config), 'post');
ElMessage.success(`添加成功`);
draftData.value = {};
config.$refresh && getList();
return result;
}
const del = async (id: string | number, config: DeleteConfig) => {
config = parseConfig(config);
const result = await onFetch(http.delete(`${url}/${id}`, config), 'post');
ElMessage.success(`删除成功`);
config.$refresh && getList();
return result;
}
return {
list,
data,
current,
draftData,
pending,
isPending,
getList,
getDetail,
update,
add,
del,
}
};
使用
// store/test.ts
import { defineStore } from "pinia";
import { useBasicStore } from "./base";
type TestState = {
name: string,
hobby: string []
}
// 直接使用
export const useTest = defineStore('test', () => useBasicStore<TestState>('/api/test'));
export const useTest1 = defineStore('test1', () => {
const state = useBasicStore<TestState>('/api/test');
return {
...state,
// 增加模块内部的行为或者覆盖basicStore内的默认行为
...someState
...someAction
}
});
useTest().getList().then(res => {
//智能提示
res.data // TestState[]
})