vue3 pinia模块化记录
Pinia在Vue3中两种不同的写法和模块化统一注册,以及数据持久化两个插件的使用方式
·
Vue3中对pinia模块化全局注册
项目小使用简易的方式还不觉得,但是项目大了后就会发现引入的东西有些重复了
安装
yarn add pinia
# or with npm
npm install pinia
挂载实例
main.ts中 挂载pinia实例
import { createPinia } from "pinia";
...
const pinia = createPinia()
app.use(pinia);
话不多说,直接贴代码
在scr下创建stores文件夹,创建index.ts文件
// 使用options API模式定义,vue2的组件模型形式类似
// import useDemoStore from "./modules/addNumber";
// export interface PiniaStore {
// useDemoStore:ReturnType<typeof useDemoStore>
// }
// const piniaStore: PiniaStore = {} as PiniaStore;
// /**
// * 注册app状态库
// */
// export const registerStore = () => {
// piniaStore.useDemoStore = useDemoStore()
// };
// export default piniaStore;
// 使用setup模式定义
import { useDemoStore } from "./modules/addNumber";
// import textContentStore from "./modules/textContent"; //单一个方法
import { textContentStore, usefruitStore } from "./modules/textContent"; //多个不同需缓存的方法
export interface PiniaStore {
useDemoStore: ReturnType<typeof useDemoStore>;
textContentStore: ReturnType<typeof textContentStore>;
usefruitStore: ReturnType<typeof usefruitStore>;
}
const piniaStore: PiniaStore = {} as PiniaStore;
/**
* 注册app状态库
*/
export const registerStore = () => {
piniaStore.useDemoStore = useDemoStore();
piniaStore.textContentStore = textContentStore();
piniaStore.usefruitStore = usefruitStore();
};
export default piniaStore;
scr/stores/modules/
新建你的store.ts
这里使用了两种不同的数据持久化插件,如果不需要可忽略插件
1、pinia-plugin-persist 插件的数据持久化使用
2、pinia-plugin-persistedstate插件
两个插件的属性使用不一样,需注意
代码使用了两个不同的写法,1、使用options API模式定义,vue2的组件模型形式类似 2、使用setup模式定义
主要是用作全局注册新增加自动引入模块,减少手动注册的操作(如有更好的方式,欢迎指教)
const appStore: { [x: string]: any } = {};
const modulesFiles = import.meta.globEager('./modules/*.ts');
const pathList: string[] = [];
for (const path in modulesFiles) {
pathList.push(path);
}
const modules = pathList.reduce((modules: { [x: string]: any }, modulePath: string) => {
const value = modulesFiles[modulePath];
for (const key in value) {
modules[key] = modulesFiles[modulePath][key];
}
return modules;
}, {});
/**
* 注册app状态库
*/
export const registerStore = () => {
for (const key in modules) {
appStore[key] = modules[key]();
}
};
export default appStore;
import { defineStore } from "pinia";
import { ref } from "vue";
// pinia-plugin-persist 插件的数据持久化使用
export const textContentStore = defineStore({
id: "goods",
state: () => {
return {
fruit: "苹果",
price: 15,
};
},
actions: {
changeName() {
this.fruit = "雪梨";
},
changePrice(val: number) {
this.price = val;
},
},
// 开启数据缓存
persist: {
enabled: true,
key: "goods",
// strategies: [
// {
// storage: localStorage,
// paths: ['accessToken']
// },
strategies: [
// 自定义存储到 sessionStorage 和 localStorage
{ key: "fruit", storage: sessionStorage, paths: ["fruit"] },
{ key: "price", storage: localStorage, paths: ["price"] },
],
},
});
export const usefruitStore = defineStore(
"goods1",
() => {
const fruit1 = ref<string>("香蕉");
const price1 = ref<number>(10);
function changeName1() {
fruit1.value = "雪梨";
}
function changePrice1(val: number) {
price1.value = val;
}
return { fruit1, price1, changeName1, changePrice1 };
},
{
//持久化存储配置 ,必须同步详情可看官方说明文档
persist: {
key: "_pinia_price1",
storage: sessionStorage,
paths: ["fruit1"],
},
}
);
// export const textContentStore = defineStore(
// "counter",
// () => {
// const fruit = ref<string>("苹果");
// const price = ref<number>(100);
// function changeName() {
// fruit.value = "雪梨";
// }
// function changePrice(val:number) {
// price.value = val
// }
// return { fruit, price, changeName, changePrice, };
// },
// // {
// // //持久化存储配置 ,必须同步详情可看官方说明文档
// // persist: {
// // key: "_pinia_fruit",
// // storage: sessionStorage,
// // paths: ["fruit"],
// // },
// // }
// );
页面
到页面上的使用
<h2>水果</h2>
<h3>名称1:{{ fruit }}---价格:{{ price }}</h3>
<button @click="changeName">修改名称</button>
<button @click="ChangePrice">修改价格</button>
--------------------------------------------
<h3>名称2:{{ fruit1 }}---价格:{{ price1 }}</h3>
<button @click="changeName1">修改名称1</button>
<button @click="changePrice1(120)">修改价格1</button>
import PiniaStore from "../stores";
import { storeToRefs } from "pinia";
// setup composition API模式
const { fruit, price } = storeToRefs(PiniaStore.textContentStore);
const { changeName, changePrice } = PiniaStore.textContentStore;
const { fruit1, price1 } = storeToRefs(PiniaStore.usefruitStore);
相对来说项目小的话没什么必要做全局,但是项目大了可能这样会好维护一些
当然也会有更好的方式,只是我没发现
最后补充
打包解耦
到这里还不行,为了让appStore实例与项目解耦,在构建时要把appStore抽取到公共chunk,在vite.config.ts做如下配置
build: {
outDir: "dist",
rollupOptions: {
output: {
manualChunks(id) {
//静态资源分拆打包
...其他配置
// 将pinia的全局库实例打包进vendor,避免和页面一起打包造成资源重复引入
if (id.includes(resolve(__dirname, "/src/store/index.ts"))) {
return "vendor";
}
},
},
},
}
开发过程中遇到的问题
1、在使用上述pinia模块化时,遇到需要监听state的变量
解构变量之后再watch它,可能会无法检测到它的变化
const { fruit, price } = storeToRefs(PiniaStore.textContentStore);
watch(()=>fruit,(newVal)=>{
console.log('newVal',newVal) //无变化
})
改用
watch(()=>PiniaStore.textContentStore.fruit,(newVal)=>{
console.log(‘newVal’,newVal) //无变化
})
更多推荐
已为社区贡献1条内容
所有评论(0)