从零开始搭建前端项目七(pinia)
从零开始一步一步搭建一个精简的前端项目。
技术栈:Vue3.0 + Vite + TypeScript + Element Plus + Vue Router + axios + Pinia
规范化:Eslint + Airbnb JavaScript Style + husky + lint-staged
包管理:yarn
历史内容
从零开始搭建前端项目一(Vue3+Vite+TS+Eslint+Airbnb+prettier)
从零开始搭建前端项目二(husky+lint-staged)
本章内容
在项目中加入轻量级状态管理库pinia,并使用。
Pinia
安装
yarn add pinia
挂载全局实例
// main.ts
import { createPinia } from 'pinia'
app.use(createPinia())
创建store
在src/store/modules/user.ts创建一个管理token的store。
// user.ts
import { ref } from 'vue';
import { defineStore } from 'pinia';
export const useTokenStore = defineStore('accessToken', () => {
const accesToken = ref<string>('');
function getAccessToken() {
return accesToken.value;
}
function setAccessToken(token: string) {
return new Promise((resolve) => {
accesToken.value = token;
window.sessionStorage.setItem('access_token', token);
resolve(true);
});
}
function clearAccessToken() {
return new Promise((resolve) => {
accesToken.value = '';
window.sessionStorage.removeItem('access_token');
resolve(true);
});
}
return { accesToken, getAccessToken, setAccessToken, clearAccessToken };
});
defineStore方法定义一个store,里面分别定义1个accesToken的state,1个getAccessToken的getters,setAccessToken 和clearAccessToken两个action 。其中state是要共享的全局状态,getters是获取state的计算结果,action则是让业务方调用来改变state的入口。
使用
在登录逻辑中使用。
// LoginForm.vue
<script lang="ts" setup name="LoginForm">
import useTokenStore from '@store/modules/user';
const piniaStore = useTokenStore();
const { accesToken } = storeToRefs(piniaStore);
const { setAccessToken } = piniaStore.useTokenStore;
const isSaveAccessTokenRes = await setAccessToken(data.access_token);
if (!isSaveAccessTokenRes) {
ElMessage.error('登录凭证存储失败!');
return;
}
// 登录凭证存储成功逻辑,路由跳转
// ...
</script>
封装优化
注册优化
在src/store目录下创建一个入口index.ts,其中包含一个注册函数registerStore(),其作用是把整个项目的store都提前注册好,最后把所有的store实例挂到piniaStore透传出去。
import { useTokenStore, useInfoStore } from '@store/modules/user';
const piniaStore: any = {};
/**
* 注册app状态库
*/
export const registerStore = () => {
piniaStore.useTokenStore = useTokenStore();
piniaStore.useInfoStore = useInfoStore();
};
export default piniaStore;
全局注册
在src/main.ts全局注册
import { createApp } from 'vue';
import App from './App.vue';
import { createPinia } from 'pinia';
import { registerStore } from './store';
const app = createApp(App);
app.use(createPinia());
// 注册pinia状态管理库
registerStore();
app.mount('#app');
使用
在登录逻辑中使用。
// LoginForm.vue
<script lang="ts" setup name="LoginForm">
import piniaStore from '@store/index';
const { setAccessToken } = piniaStore.useTokenStore;
const isSaveAccessTokenRes = await setAccessToken(data.access_token);
if (!isSaveAccessTokenRes) {
ElMessage.error('登录凭证存储失败!');
return;
}
// 登录凭证存储成功逻辑,路由跳转
// ...
}
</script>
打包解耦
让piniaStore实例与项目解耦,在构建时要把piniaStore抽取到公共chunk,在vite.config.ts做如下配置
// vite.config.ts
export default defineConfig((env: ConfigEnv) => {
return {
// ...
build: {
// ...
rollupOptions: {
output: {
manualChunks(id) {
// 将pinia的全局库实例打包进vendor,避免和页面一起打包造成资源重复引入
if (id.includes(resolve(__dirname, './src/store/index.ts'))) {
return 'vendor';
}
}
}
}
}
};
});
小结
介绍轻量级状态管理库pinia,针对本项目的引入,创建,优化,使用和打包。