从零开始搭建前端项目七(pinia)

998 阅读2分钟

从零开始搭建前端项目七(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)

从零开始搭建前端项目三(Element Plus)

从零开始搭建前端项目四(Vue Router)

从零开始搭建前端项目五(vite.config.ts优化)

从零开始搭建前端项目六(axios+mock)

本章内容

在项目中加入轻量级状态管理库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,setAccessTokenclearAccessToken两个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,针对本项目的引入,创建,优化,使用和打包。

参考文章:Pinia进阶:优雅的setup(函数式)写法+封装到你的企业项目 - 掘金