找回密码
 立即注册
首页 业界区 业界 Vue3.0+typescript+Vite+Pinia+Element-plus搭建vue3框 ...

Vue3.0+typescript+Vite+Pinia+Element-plus搭建vue3框架!

篙菠 2025-6-6 15:09:23
使用 Vite 快速搭建脚手架

命令行选项直接指定项目名称和想要使用的模板,Vite + Vue 项目,运行(推荐使用yarn)
  1. # npm 6.x
  2. npm init vite@latest my-vue-app --template vue
  3. # npm 7+, 需要额外的双横线:
  4. npm init vite@latest my-vue-app -- --template vue
  5. # yarn
  6. yarn create vite my-vue-app --template vue
  7. # pnpm
  8. pnpm create vite my-vue-app -- --template vue
复制代码
这里我们想要直接生成一个Vue3+Vite2+ts的项目模板,因此我们执行的命令是: yarn create vite my-vue-app --template vue-ts,这样我们就不需要你单独的再去安装配置ts了。

<img alt="" loading="lazy">

cd 到项目文件夹,安装node_modules依赖,运行项目
  1. # cd进入my-vue-app项目文件夹
  2. cd my-vue-app
  3. # 安装依赖
  4. yarn
  5. # 运行项目
  6. yarn dev
复制代码
<img alt="" loading="lazy">

至此,一个最纯净的vue3.0+vite2+typescript项目就完成了。在浏览地址栏中输入http://localhost:3000/,就看到了如下的启动页,然后就可以安装所需的插件了。
<img alt="" loading="lazy">

配置文件路径引用别名 alias

修改vite.config.ts中的reslove的配置
  1. import { defineConfig } from 'vite'
  2. import vue from '@vitejs/plugin-vue'
  3. import path from 'path'
  4. // https://vitejs.dev/config/
  5. export default defineConfig({
  6.   plugins: [vue()],
  7.   resolve: {
  8.     alias: {
  9.       '@': path.resolve(__dirname, 'src'),
  10.     },
  11.   },
  12. })
复制代码
在修改tsconfig.json文件的配置
  1. {
  2.   "compilerOptions": {
  3.     "target": "esnext",
  4.     "module": "esnext",
  5.     "moduleResolution": "node",
  6.     "strict": true,
  7.     "jsx": "preserve",
  8.     "sourceMap": true,
  9.     "resolveJsonModule": true,
  10.     "esModuleInterop": true,
  11.     "lib": ["esnext", "dom"],
  12.     "baseUrl": ".",
  13.     "paths": {
  14.       "@/*":["src/*"]
  15.     }
  16.   },
  17.   "include": [
  18.     "src/**/*.ts",
  19.     "src/**/*.d.ts",
  20.     "src/**/*.tsx",
  21.     "src/**/*.vue"
  22.   ]
  23. }
复制代码
配置路由

安装
  1. # npm
  2. npm install vue-router@4
  3. # yarn
  4. yarn add vue-router@4
复制代码
在src下新建router文件夹,用来集中管理路由,在router文件夹下新建  index.ts文件。
  1. import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
  2. const routes: RouteRecordRaw[] = [
  3.   {
  4.     path: '/',
  5.     name: 'Login',
  6.     // 注意这里要带上文件后缀.vue
  7.     component: () => import('@/pages/login/Login.vue'),
  8.     meta: {
  9.       title: '登录',
  10.     },
  11.   },
  12. ]
  13. const router = createRouter({
  14.   history: createWebHistory(),
  15.   routes,
  16.   strict: true,
  17.   // 期望滚动到哪个的位置
  18.   scrollBehavior(to, from, savedPosition) {
  19.     return new Promise(resolve => {
  20.       if (savedPosition) {
  21.         return savedPosition;
  22.       } else {
  23.         if (from.meta.saveSrollTop) {
  24.           const top: number =
  25.             document.documentElement.scrollTop || document.body.scrollTop;
  26.           resolve({ left: 0, top });
  27.         }
  28.       }
  29.     });
  30.   }
  31. })
  32. export function setupRouter(app: App) {
  33.   app.use(router);
  34. }
  35. export default router
复制代码
修改入口文件 mian.ts
  1. import { createApp } from "vue";
  2. import App from "./App.vue";
  3. import router, { setupRouter } from './router';
  4. const app = createApp(App);
  5. // 挂在路由
  6. setupRouter(app);
  7. // 路由准备就绪后挂载APP实例
  8. await router.isReady();
  9. app.mount('#app', true);
复制代码
更多的路由配置可以移步vue-router(https://next.router.vuejs.org/zh/introduction.html)。 vue-router4.x支持typescript,路由的类型为RouteRecordRaw。meta字段可以让我们根据不同的业务需求扩展 RouteMeta 接口来输入它的多样性。以下的meta中的配置仅供参考:
  1. // typings.d.ts or router.ts
  2. import 'vue-router'
  3. declare module 'vue-router' {
  4.   interface RouteMeta {
  5.     // 页面标题,通常必选。
  6.     title: string;
  7.     // 菜单图标
  8.     icon?: string;
  9.     // 配置菜单的权限
  10.     permission: string[];
  11.     // 是否开启页面缓存
  12.     keepAlive?: boolean;
  13.     // 二级页面我们并不想在菜单中显示
  14.     hidden?: boolean;
  15.     // 菜单排序
  16.     order?: number;
  17.     // 嵌套外链
  18.     frameUrl?: string;
  19.   }
  20. }
复制代码
配置 css 预处理器 scss

安装
  1. yarn add sass-loader --dev
  2. yarn add dart-sass --dev
  3. yarn add sass --dev
复制代码
配置全局 scss 样式文件 在 src文件夹下新增 styles 文件夹,用于存放全局样式文件,新建一个 varibles.scss文件,用于统一管理声明的颜色变量:
  1. $white: #FFFFFF;
  2. $primary-color: #1890ff;
  3. $success-color: #67C23A;
  4. $warning-color: #E6A23C;
  5. $danger-color: #F56C6C;
  6. $info-color: #909399;
复制代码
组件中使用在vite.config.ts中将这个样式文件全局注入到项目即可全局使用,不需要在任何组件中再次引入这个文件或者颜色变量。
  1. css: {
  2.   preprocessorOptions: {
  3.     scss: {
  4.       modifyVars: {},
  5.       javascriptEnabled: true,
  6.       // 注意这里的引入的书写
  7.       additionalData: '@import "@/style/varibles.scss";'
  8.     }
  9.   }
  10. },
复制代码
在组件中使用
  1. .div {
  2.   color: $primary-color;
  3.   background-color: $success-color;
  4. }
复制代码
统一请求封装

在src文件夹下,新建http文件夹,在http文件夹下新增index.ts,config.ts,core.ts,types.d.ts,utils.ts

core.ts
  1. import Axios, { AxiosRequestConfig, CancelTokenStatic, AxiosInstance } from "axios";
  2. import NProgress from 'nprogress'
  3. import { genConfig } from "./config";
  4. import { transformConfigByMethod } from "./utils";
  5. import {
  6.   cancelTokenType,
  7.   RequestMethods,
  8.   HttpRequestConfig,
  9.   HttpResoponse,
  10.   HttpError
  11. } from "./types.d";
  12. class Http {
  13.   constructor() {
  14.     this.httpInterceptorsRequest();
  15.     this.httpInterceptorsResponse();
  16.   }
  17.   // 初始化配置对象
  18.   private static initConfig: HttpRequestConfig = {};
  19.   // 保存当前Axios实例对象
  20.   private static axiosInstance: AxiosInstance = Axios.create(genConfig());
  21.   // 保存 Http实例
  22.   private static HttpInstance: Http;
  23.   // axios取消对象
  24.   private CancelToken: CancelTokenStatic = Axios.CancelToken;
  25.   // 取消的凭证数组
  26.   private sourceTokenList: Array<cancelTokenType> = [];
  27.   // 记录当前这一次cancelToken的key
  28.   private currentCancelTokenKey = "";
  29.   public get cancelTokenList(): Array<cancelTokenType> {
  30.     return this.sourceTokenList;
  31.   }
  32.   // eslint-disable-next-line class-methods-use-this
  33.   public set cancelTokenList(value) {
  34.     throw new Error("cancelTokenList不允许赋值");
  35.   }
  36.   /**
  37.    * @description 私有构造不允许实例化
  38.    * @returns void 0
  39.    */
  40.   // constructor() {}
  41.   /**
  42.    * @description 生成唯一取消key
  43.    * @param config axios配置
  44.    * @returns string
  45.    */
  46.   // eslint-disable-next-line class-methods-use-this
  47.   private static genUniqueKey(config: HttpRequestConfig): string {
  48.     return `${config.url}--${JSON.stringify(config.data)}`;
  49.   }
  50.   /**
  51.    * @description 取消重复请求
  52.    * @returns void 0
  53.    */
  54.   private cancelRepeatRequest(): void {
  55.     const temp: { [key: string]: boolean } = {};
  56.     this.sourceTokenList = this.sourceTokenList.reduce>(
  57.       (res: Array<cancelTokenType>, cancelToken: cancelTokenType) => {
  58.         const { cancelKey, cancelExecutor } = cancelToken;
  59.         if (!temp[cancelKey]) {
  60.           temp[cancelKey] = true;
  61.           res.push(cancelToken);
  62.         } else {
  63.           cancelExecutor();
  64.         }
  65.         return res;
  66.       },
  67.       []
  68.     );
  69.   }
  70.   /**
  71.    * @description 删除指定的CancelToken
  72.    * @returns void 0
  73.    */
  74.   private deleteCancelTokenByCancelKey(cancelKey: string): void {
  75.     this.sourceTokenList =
  76.       this.sourceTokenList.length < 1
  77.         ? this.sourceTokenList.filter(
  78.             cancelToken => cancelToken.cancelKey !== cancelKey
  79.           )
  80.         : [];
  81.   }
  82.   /**
  83.    * @description 拦截请求
  84.    * @returns void 0
  85.    */
  86.   private httpInterceptorsRequest(): void {
  87.     Http.axiosInstance.interceptors.request.use(
  88.       (config: HttpRequestConfig) => {
  89.         const $config = config;
  90.         NProgress.start(); // 每次切换页面时,调用进度条
  91.         const cancelKey = Http.genUniqueKey($config);
  92.         $config.cancelToken = new this.CancelToken(
  93.           (cancelExecutor: (cancel: any) => void) => {
  94.             this.sourceTokenList.push({ cancelKey, cancelExecutor });
  95.           }
  96.         );
  97.         this.cancelRepeatRequest();
  98.         this.currentCancelTokenKey = cancelKey;
  99.         // 优先判断post/get等方法是否传入回掉,否则执行初始化设置等回掉
  100.         if (typeof config.beforeRequestCallback === "function") {
  101.           config.beforeRequestCallback($config);
  102.           return $config;
  103.         }
  104.         if (Http.initConfig.beforeRequestCallback) {
  105.           Http.initConfig.beforeRequestCallback($config);
  106.           return $config;
  107.         }
  108.         return $config;
  109.       },
  110.       error => {
  111.         return Promise.reject(error);
  112.       }
  113.     );
  114.   }
  115.   /**
  116.    * @description 清空当前cancelTokenList
  117.    * @returns void 0
  118.    */
  119.   public clearCancelTokenList(): void {
  120.     this.sourceTokenList.length = 0;
  121.   }
  122.   /**
  123.    * @description 拦截响应
  124.    * @returns void 0
  125.    */
  126.   private httpInterceptorsResponse(): void {
  127.     const instance = Http.axiosInstance;
  128.     instance.interceptors.response.use(
  129.       (response: HttpResoponse) => {
  130.         const $config = response.config;
  131.         // 请求每次成功一次就删除当前canceltoken标记
  132.         const cancelKey = Http.genUniqueKey($config);
  133.         this.deleteCancelTokenByCancelKey(cancelKey);
  134.         NProgress.done();
  135.         // 优先判断post/get等方法是否传入回掉,否则执行初始化设置等回掉
  136.         if (typeof $config.beforeResponseCallback === "function") {
  137.           $config.beforeResponseCallback(response);
  138.           return response.data;
  139.         }
  140.         if (Http.initConfig.beforeResponseCallback) {
  141.           Http.initConfig.beforeResponseCallback(response);
  142.           return response.data;
  143.         }
  144.         return response.data;
  145.       },
  146.       (error: HttpError) => {
  147.         const $error = error;
  148.         // 判断当前的请求中是否在 取消token数组理存在,如果存在则移除(单次请求流程)
  149.         if (this.currentCancelTokenKey) {
  150.           const haskey = this.sourceTokenList.filter(
  151.             cancelToken => cancelToken.cancelKey === this.currentCancelTokenKey
  152.           ).length;
  153.           if (haskey) {
  154.             this.sourceTokenList = this.sourceTokenList.filter(
  155.               cancelToken =>
  156.                 cancelToken.cancelKey !== this.currentCancelTokenKey
  157.             );
  158.             this.currentCancelTokenKey = "";
  159.           }
  160.         }
  161.         $error.isCancelRequest = Axios.isCancel($error);
  162.         NProgress.done();
  163.         // 所有的响应异常 区分来源为取消请求/非取消请求
  164.         return Promise.reject($error);
  165.       }
  166.     );
  167.   }
  168.   public request<T>(
  169.     method: RequestMethods,
  170.     url: string,
  171.     param?: AxiosRequestConfig,
  172.     axiosConfig?: HttpRequestConfig
  173.   ): Promise<T> {
  174.     const config = transformConfigByMethod(param, {
  175.       method,
  176.       url,
  177.       ...axiosConfig
  178.     } as HttpRequestConfig);
  179.     // 单独处理自定义请求/响应回掉
  180.     return new Promise((resolve, reject) => {
  181.       Http.axiosInstance
  182.         .request(config)
  183.         .then((response: undefined) => {
  184.           resolve(response);
  185.         })
  186.         .catch((error: any) => {
  187.           reject(error);
  188.         });
  189.     });
  190.   }
  191.   public post<T>(
  192.     url: string,
  193.     params?: T,
  194.     config?: HttpRequestConfig
  195.   ): Promise<T> {
  196.     return this.request<T>("post", url, params, config);
  197.   }
  198.   public get<T>(
  199.     url: string,
  200.     params?: T,
  201.     config?: HttpRequestConfig
  202.   ): Promise<T> {
  203.     return this.request<T>("get", url, params, config);
  204.   }
  205. }
  206. export default Http;
复制代码
config.ts
  1. import { AxiosRequestConfig } from "axios";
  2. import { excludeProps } from "./utils";
  3. /**
  4. * 默认配置
  5. */
  6. export const defaultConfig: AxiosRequestConfig = {
  7.   baseURL: "",
  8.   //10秒超时
  9.   timeout: 10000,
  10.   headers: {
  11.     Accept: "application/json, text/plain, */*",
  12.     "Content-Type": "application/json",
  13.     "X-Requested-With": "XMLHttpRequest"
  14.   }
  15. };
  16. export function genConfig(config?: AxiosRequestConfig): AxiosRequestConfig {
  17.   if (!config) {
  18.     return defaultConfig;
  19.   }
  20.   const { headers } = config;
  21.   if (headers && typeof headers === "object") {
  22.     defaultConfig.headers = {
  23.       ...defaultConfig.headers,
  24.       ...headers
  25.     };
  26.   }
  27.   return { ...excludeProps(config!, "headers"), ...defaultConfig };
  28. }
  29. export const METHODS = ["post", "get", "put", "delete", "option", "patch"];
复制代码
utils.ts
  1. import { HttpRequestConfig } from "./types.d";
  2. export function excludeProps<T extends { [key: string]: any }>(
  3.   origin: T,
  4.   prop: string
  5. ): { [key: string]: T } {
  6.   return Object.keys(origin)
  7.     .filter(key => !prop.includes(key))
  8.     .reduce((res, key) => {
  9.       res[key] = origin[key];
  10.       return res;
  11.     }, {} as { [key: string]: T });
  12. }
  13. export function transformConfigByMethod(
  14.   params: any,
  15.   config: HttpRequestConfig
  16. ): HttpRequestConfig {
  17.   const { method } = config;
  18.   const props = ["delete", "get", "head", "options"].includes(
  19.     method!.toLocaleLowerCase()
  20.   )
  21.     ? "params"
  22.     : "data";
  23.   return {
  24.     ...config,
  25.     [props]: params
  26.   };
  27. }
复制代码
types.d.ts
  1. import Axios, {
  2.   AxiosRequestConfig,
  3.   Canceler,
  4.   AxiosResponse,
  5.   Method,
  6.   AxiosError
  7. } from "axios";
  8. import { METHODS } from "./config";
  9. export type cancelTokenType = { cancelKey: string; cancelExecutor: Canceler };
  10. export type RequestMethods = Extract<
  11.   Method,
  12.   "get" | "post" | "put" | "delete" | "patch" | "option" | "head"
  13. >;
  14. export interface HttpRequestConfig extends AxiosRequestConfig {
  15.   // 请求发送之前
  16.   beforeRequestCallback?: (request: HttpRequestConfig) => void;
  17.   // 相应返回之前
  18.   beforeResponseCallback?: (response: HttpResoponse) => void;
  19. }
  20. export interface HttpResoponse extends AxiosResponse {
  21.   config: HttpRequestConfig;
  22. }
  23. export interface HttpError extends AxiosError {
  24.   isCancelRequest?: boolean;
  25. }
  26. export default class Http {
  27.   cancelTokenList: Array<cancelTokenType>;
  28.   clearCancelTokenList(): void;
  29.   request<T>(
  30.     method: RequestMethods,
  31.     url: string,
  32.     param?: AxiosRequestConfig,
  33.     axiosConfig?: HttpRequestConfig
  34.   ): Promise<T>;
  35.   post<T>(
  36.     url: string,
  37.     params?: T,
  38.     config?: HttpRequestConfig
  39.   ): Promise<T>;
  40.   get<T>(
  41.     url: string,
  42.     params?: T,
  43.     config?: HttpRequestConfig
  44.   ): Promise<T>;
  45. }
复制代码
index.ts
  1. import Http from "./core";
  2. export const http = new Http();
复制代码
统一api管理

在src下新增api文件夹,对项目中接口做统一管理,按照模块来划分。
例如,在 api 文件下新增 user.ts和types.ts ,分别用于存放登录,注册等模块的请求接口和数据类型。
  1. // login.ts
  2. import { http } from "@/http/index";
  3. import { ILoginReq, ILoginRes } from "./types";
  4. export const getLogin = async(req: ILoginParams): Promise<ILoginRes> => {
  5.   const res:any = await http.post('/login/info', req)
  6.   return res as ILoginRes
  7. }
  8. # 或者
  9. export const getLogin1 = async(req: ILoginParams): Promise<ILoginRes> => {
  10.   const res:any = await http.request('post', '/login/info', req)
  11.   return res as ILoginRes
  12. }
复制代码
  1. // types.ts
  2. export interface ILoginReq {
  3.   userName: string;
  4.   password: string;
  5. }
  6. export interface ILoginRes {
  7.   access_token: string;
  8.   refresh_token: string;
  9.   scope: string
  10.   token_type: string
  11.   expires_in: string
  12. }
复制代码
除了自己手动封装 axios ,这里还推荐一个十分非常强大牛皮的 vue3 的请求库: VueRequest,里面的功能非常的丰富(偷偷告诉你我也在使用中)。官网地址:https://www.attojs.com/
状态管理 Pinia

Pinia 是 Vue.js 的轻量级状态管理库,最近很受欢迎。它使用 Vue 3 中的新反应系统来构建一个直观且完全类型化的状态管理库。
由于 vuex 4 对 typescript 的支持很不友好,所以状态管理弃用了 vuex 而采取了 pinia, pinia 的作者是 Vue 核心团队成员,并且pinia已经正式加入了Vue,成为了Vue中的一员。尤大佬 pinia 可能会代替 vuex,所以请放心使用(公司项目也在使用中)。
Pinia官网地址(https://pinia.vuejs.org)
Pinia的一些优点:
(1)Pinia 的 API 设计非常接近 Vuex 5 的提案。
(2)无需像 Vuex 4 自定义复杂的类型来支持 typescript,天生具备完美的类型推断。
(3)模块化设计,你引入的每一个 store 在打包时都可以自动拆分他们。
(4)无嵌套结构,但你可以在任意的 store 之间交叉组合使用。
(5)Pinia 与 Vue devtools 挂钩,不会影响 Vue 3 开发体验。
<img alt="" loading="lazy">

Pinia的成功可以归功于其管理存储数据的独特功能(可扩展性、存储模块组织、状态变化分组、多存储创建等)。
另一方面,Vuex也是为Vue框架建立的一个流行的状态管理库,它也是Vue核心团队推荐的状态管理库。Vuex高度关注应用程序的可扩展性、开发人员的工效和信心。它基于与Redux相同的流量架构。
Pinia和Vuex都非常快,在某些情况下,使用Pinia的web应用程序会比使用Vuex更快。这种性能的提升可以归因于Pinia的极轻的体积,Pinia体积约1KB。
安装
  1. # 安装
  2. yarn add pinia@next
复制代码
在src下新建store文件夹,在store文件夹下新建index.ts,mutation-types(变量集中管理),types.ts(类型)和modules文件夹(分模块管理状态)

<img alt="" loading="lazy">
  1. // index.ts
  2. import type { App } from "vue";
  3. import { createPinia } from "pinia";
  4. const store = createPinia();
  5. export function setupStore(app: App<Element>) {
  6.     app.use(store)
  7. }
  8. export { store }
复制代码
  1. // modules/user.ts
  2. import { defineStore } from 'pinia';
  3. import { store } from '@/store';
  4. import { ACCESS_TOKEN } from '@/store/mutation-types';
  5. import { IUserState } from '@/store/types'
  6. export const useUserStore = defineStore({
  7.   // 此处的id很重要
  8.   id: 'app-user',
  9.   state: (): IUserState => ({
  10.     token: localStorge.getItem(ACCESS_TOKEN)
  11.   }),
  12.   getters: {
  13.     getToken(): string {
  14.       return this.token;
  15.     }
  16.   },
  17.   actions: {
  18.     setToken(token: string) {
  19.       this.token = token;
  20.     },
  21.     // 登录
  22.     async login(userInfo) {
  23.       try {
  24.         const response = await login(userInfo);
  25.         const { result, code } = response;
  26.         if (code === ResultEnum.SUCCESS) {
  27.           localStorage.setItem(ACCESS_TOKEN, result.token);
  28.           this.setToken(result.token);
  29.         }
  30.         return Promise.resolve(response);
  31.       } catch (e) {
  32.         return Promise.reject(e);
  33.       }
  34.     },
  35.   }
  36. })
  37. // Need to be used outside the setup
  38. export function useUserStoreHook() {
  39.   return useUserStore(store);
  40. }
复制代码
  1. /// mutation-types.ts
  2. // 对变量做统一管理
  3. export const ACCESS_TOKEN = 'ACCESS-TOKEN'; // 用户token
复制代码
修改main.ts
  1. import { createApp } from 'vue'
  2. import App from './App.vue'
  3. import { setupStore } from '@/store'
  4. import router from './router/index'
  5. const app = createApp(App)
  6. // 挂载状态管理
  7. setupStore(app);
  8. app.use(router)
  9. app.mount('#app')
复制代码
在组件中使用
  1. <template>
  2.   {{userStore.token}}
  3. </template>
复制代码
getters的用法介绍
  1. // modules/user.ts
  2. import { defineStore } from 'pinia';
  3. import { store } from '@/store';
  4. import { ACCESS_TOKEN } from '@/store/mutation-types';
  5. import { IUserState } from '@/store/types'
  6. export const useUserStore = defineStore({
  7.   // 此处的id很重要
  8.   id: 'app-user',
  9.   state: (): IUserState => ({
  10.     token: localStorge.getItem(ACCESS_TOKEN),
  11.     name: ''
  12.   }),
  13.   getters: {
  14.     getToken(): string {
  15.       return this.token;
  16.     },
  17.     nameLength: (state) => state.name.length,
  18.   },
  19.   actions: {
  20.     setToken(token: string) {
  21.       this.token = token;
  22.     },
  23.     // 登录
  24.     async login(userInfo) {
  25.       // 调用接口,做逻辑处理
  26.     }
  27.   }
  28. })
  29. // Need to be used outside the setup
  30. export function useUserStoreHook() {
  31.   return useUserStore(store);
  32. }
复制代码
  1. <template>
  2.   
  3.    {{userStore.name}}
  4.   {{userStore.nameLength}}
  5.   <buttton @click="changeName"></button>
  6.   
  7. </template>
复制代码
actions

这里与 Vuex 有极大的不同,Pinia 仅提供了一种方法来定义如何更改状态的规则,放弃 mutations 只依靠 Actions,这是一项重大的改变。
Pinia 让 Actions 更加的灵活

  • 可以通过组件或其他 action 调用
  • 可以从其他 store 的 action 中调用
  • 直接在商店实例上调用
  • 支持同步异步
  • 有任意数量的参数
  • 可以包含有关如何更改状态的逻辑(也就是 vuex 的 mutations 的作用)
  • 可以 $patch 方法直接更改状态属性
    更多详细的用法请参考Pinia中的actions官方网站:
    actions的用法(https://pinia.vuejs.org/core-concepts/actions.html)
环境变量配置

vite 提供了两种模式:具有开发服务器的开发模式(development)和生产模式(production)。在项目的根目录中我们新建开发配置文件.env.development和生产配置文件.env.production。
  1. # 网站根目录
  2. VITE_APP_BASE_URL= ''
复制代码
组件中使用:
  1. console.log(import.meta.env.VITE_APP_BASE_URL)
复制代码
配置 package.json,打包区分开发环境和生产环境
  1. "build:dev": "vue-tsc --noEmit && vite build --mode development",
  2. "build:pro": "vue-tsc --noEmit && vite build --mode production",
复制代码
使用组件库

根据自己的项目需要选择合适的组件库即可,这里推荐两个优秀的组件库Element-plus和Naive UI。下面简单介绍它们的使用方法。
使用element-plus(https://element-plus.gitee.io/zh-CN/)
  1. yarn add element-plus
复制代码
推荐按需引入的方式:
按需引入需要安装unplugin-vue-components和unplugin-auto-import两个插件。
  1. yarn add -D unplugin-vue-components unplugin-auto-import
复制代码
再将vite.config.ts写入一下配置,即可在项目中使用element plus组件,无需再引入。
  1. // vite.config.ts
  2. import AutoImport from 'unplugin-auto-import/vite'
  3. import Components from 'unplugin-vue-components/vite'
  4. import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
  5. export default {
  6.   plugins: [
  7.     // ...
  8.     AutoImport({
  9.       resolvers: [ElementPlusResolver()],
  10.     }),
  11.     Components({
  12.       resolvers: [ElementPlusResolver()],
  13.     }),
  14.   ],
  15. }
复制代码
Naive UI(https://www.naiveui.com/zh-CN/os-theme)
  1. # 安装naive-ui
  2. npm i -D naive-ui
  3. # 安装字体
  4. npm i -D vfonts
复制代码
按需全局安装组件
  1. import { createApp } from 'vue'
  2. import {
  3.   // create naive ui
  4.   create,
  5.   // component
  6.   NButton
  7. } from 'naive-ui'
  8. const naive = create({
  9.   components: [NButton]
  10. })
  11. const app = createApp()
  12. app.use(naive)
复制代码
安装后,你可以这样在 SFC 中使用你安装的组件。
  1. <template>
  2.   <n-button>naive-ui</n-button>
  3. </template>
复制代码
Vite 常用基础配置

基础配置

运行代理和打包配置
  1. server: {
  2.     host: '0.0.0.0',
  3.     port: 3000,
  4.     open: true,
  5.     https: false,
  6.     proxy: {}
  7. },
复制代码
生产环境去除 console debugger
  1. build:{
  2.   ...
  3.   terserOptions: {
  4.       compress: {
  5.         drop_console: true,
  6.         drop_debugger: true
  7.       }
  8.   }
  9. }
复制代码
生产环境生成 .gz 文件,开启 gzip 可以极大的压缩静态资源,对页面加载的速度起到了显著的作用。使用 vite-plugin-compression 可以 gzip 或 brotli 的方式来压缩资源,这一步需要服务器端的配合,vite 只能帮你打包出 .gz 文件。此插件使用简单,你甚至无需配置参数,引入即可。
  1. # 安装
  2. yarn add --dev vite-plugin-compression
复制代码
  1. // vite.config.ts中添加
  2. import viteCompression from 'vite-plugin-compression'
  3. // gzip压缩 生产环境生成 .gz 文件
  4. viteCompression({
  5.   verbose: true,
  6.   disable: false,
  7.   threshold: 10240,
  8.   algorithm: 'gzip',
  9.   ext: '.gz',
  10. }),
复制代码
最终 vite.config.ts文件配置如下(自己根据项目需求配置即可)
  1. import { defineConfig } from 'vite'
  2. import vue from '@vitejs/plugin-vue'
  3. import path from 'path'
  4. //@ts-ignore
  5. import viteCompression from 'vite-plugin-compression'
  6. // https://vitejs.dev/config/
  7. export default defineConfig({
  8.   base: './', //打包路径
  9.   plugins: [
  10.     vue(),
  11.     // gzip压缩 生产环境生成 .gz 文件
  12.     viteCompression({
  13.       verbose: true,
  14.       disable: false,
  15.       threshold: 10240,
  16.       algorithm: 'gzip',
  17.       ext: '.gz',
  18.     }),
  19.   ],
  20.   // 配置别名
  21.   resolve: {
  22.     alias: {
  23.       '@': path.resolve(__dirname, 'src'),
  24.     },
  25.   },
  26.   css:{
  27.     preprocessorOptions:{
  28.       scss:{
  29.         additionalData:'@import "@/assets/style/mian.scss";'
  30.       }
  31.     }
  32.   },
  33.   //启动服务配置
  34.   server: {
  35.     host: '0.0.0.0',
  36.     port: 8000,
  37.     open: true,
  38.     https: false,
  39.     proxy: {}
  40.   },
  41.   // 生产环境打包配置
  42.   //去除 console debugger
  43.   build: {
  44.     terserOptions: {
  45.       compress: {
  46.         drop_console: true,
  47.         drop_debugger: true,
  48.       },
  49.     },
  50.   },
  51. })
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册