小工具知识网

当前位置: 首页 > 行业知识 > vite + vue + typscript + pinia + axios + vue-router + elementPlus

行业知识

vite + vue + typscript + pinia + axios + vue-router + elementPlus

2026-11-06 11:54:09 来源:互联网转载
npm create vite@latest

创建项目后

npm inpm run dev
"dependencies": {    "vue": "^3.4.21"  },"devDependencies": {  "@vitejs/plugin-vue": "^5.0.4",  "typescript": "^5.2.2",  "vite": "^5.2.0",  "vue-tsc": "^2.0.6"}

需要安装的插件表格(希望需要安装的插件越来越少!!!)

插件名称备注
pinia等同与 vuex
pinia-plugin-persistedstatepinia持久化插件
axiosapi请求库
vue-router路由
elementPlusUI框架
unplugin-auto-import为 Vite、Webpack、Rollup 和 esbuild 按需自动导入 API。支持 TypeScript。
unplugin-vue-componentsVue 的按需组件自动导入。
vite-plugin-compression压缩大文件
vite-plugin-style-import它会根据需要自动导入组件的样式文件
rollup-plugin-visualizer这是一个依赖分析插件,它提供了多种模式的依赖分析,包括直观的视图分析,sunburst(循环层次图,像光谱)、treemap(矩形层次图,看起来比较直观,也是默认参数)、network(网格图,查看包含关系)、raw-data(原数据模式,json格式), list(列表模式)
eslinteslint针对的是javascript,他是一个检测工具,包含js语法以及少部分格式问题,在eslint看来,语法对了就能;保证代码正常允许,格式问题属于其次;
prettierprettier属于格式化工具,它看不惯格式不统一,所以它就把eslint没干好的事接着干,另外,prettier支持,包含js在内的多种语言
@vitejs/plugin-legacy为打包后的文件提供传统浏览器兼容性支持。
unplugin-icons自动按需加载在图标,包括element plus 但是不仅仅时 element plus;使用教程请点击,具体包含图标内容查看iconify官网请点击,unplugin-icons github请点击

添加基础路径

TS版本需要安装@types/node,不然会警告找不到对应的类型声明

npm install @types/node --save-dev

vite.config.ts

import { defineConfig } from 'vite'import vue from '@vitejs/plugin-vue'import { fileURLToPath, URL } from 'node:url'// https://vitejs.dev/config/export default defineConfig({  plugins: [vue()],  resolve: {    alias: {      '@': fileURLToPath(new URL('./src', import.meta.url))    }  },})

引入TS 文件会报错找不到相应类型声明,因为在配置好 vite.config.ts 文件后

tsconfig.json 文件 或者 jsconfig.json 文件也要进行文件系统路径别名设置。需要配置baseUrl和paths字段

tsconfig.json

{  "compilerOptions": {    "target": "ESNext",    "useDefineForClassFields": true,    "module": "ESNext",    "moduleResolution": "Node",    "strict": true,    "jsx": "preserve",    "resolveJsonModule": true,    "isolatedModules": true,    "esModuleInterop": true,    "lib": ["ESNext", "DOM"],    "skipLibCheck": true,    "noEmit": true,    "types": ["element-plus/global"],    "baseUrl": "./",  // 解析非相对模块的基础地址,默认是当前目录    "paths": {      "@/*": ["./src/*"]  // 路径映射,相对于baseUrl    }  },   "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],  "references": [{ "path": "./tsconfig.node.json" }]}

安装 pinia

pnpm install --save pinianpm i pinia-plugin-persistedstate
"dependencies": {    "pinia": "^2.1.7",    "pinia-plugin-persistedstate": "^3.2.1",    "vue": "^3.4.21"  },
创建文件夹:src\store\index.ts

主要是创建一个实例

import type { App } from 'vue'import { createPinia } from 'pinia'import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' //数据持久化const store = createPinia()store.use(piniaPluginPersistedstate)export const setupStore = (app: App) => {  app.use(store)}export { store }
挂载vue
import { createApp } from 'vue'import './style.css'import App from './App.vue'import { setupStore } from '@/store'const app = createApp(App)setupStore(app)app.mount('#app')
使用时:

创建:src/store/modules/user.ts

import { defineStore } from 'pinia'interface UserState {  userInfo?: string  tokenKey: string  token: string  roleRouters?: string[]  rememberMe: boolean  loginInfo?: string}export const useUserStore = defineStore('user', {  state: (): UserState => {    return {      userInfo: undefined,      tokenKey: '',      token: '',      roleRouters: undefined,      rememberMe: true,      loginInfo: undefined    }  },  getters: {    getTokenKey(): string {      return this.tokenKey    },    getToken(): string {      return this.token    },  },  actions: {    setTokenKey(tokenKey: string) {      this.tokenKey = tokenKey    },    setToken(token: string) {      this.token = token    },  },  // persist: true // 一键开启数据持久化,使用默认配置  // 开启数据持久化,自定义配置  persist: { // Key 用于引用 storage 中的数据  // 这个 Store 将被持久化存储在 localStorage 中的 my-custom-key key 中。    key: 'my-custom-key',     // 将数据持久化到 storage 中,必须具有 getItem: (key: string) => string | null 和 setItem: (key: string, value: string) => void 两个方法。// 这个 store 将被持久化存储在 sessionStorage中。    storage: sessionStorage,     // 用于指定 state 中哪些数据需要被持久化。[] 表示不持久化任何状态,undefined 或 null 表示持久化整个 state。    // 该 store 中, 只有userInfo 和 rememberMe 被持久化,而其他不会被持久化。    paths: ['userInfo', 'rememberMe'],     // 该 hook 将在从 storage 中恢复数据之前触发,并且它可以访问整个 PiniaPluginContext,这可用于在恢复数据之前强制地执行特定的操作。    beforeRestore: (ctx) => {      console.log(`即将恢复 '${ctx.store.$id}'`)    },    // 该 hook 将在从 storage 中恢复数据之后触发,并且它可以访问整个 PiniaPluginContext,这可用于在恢复数据之后强制地执行特定的操作。    afterRestore: (ctx) => {      console.log(`刚刚恢复完 '${ctx.store.$id}'`)    },    // 当设置为 true 时,持久化/恢复 Store 时可能发生的任何错误都将使用 console.error 输出。    debug: true  },})
在组件中使用
import {useUserStore} from '@/store/modules/user';const store = useUserStore();// ...store.setTokenKey({...}); // 直接调用是不是很方便// ...store.user.page; // 直接获取
更多详细使用请点击此处

安装axios

pnpm i axios// 或者npm i axios

创建文件: src\utils\request.ts

import axios from 'axios';// 配置新建一个 axios 实例const service = axios.create({baseURL: import.meta.env.VITE_API_URL, // 环境变量timeout: 50000,headers: { 'Content-Type': 'application/json' },});// 添加请求拦截器service.interceptors.request.use((config) => {// 在发送请求之前做些什么return config;},(error) => {// 对请求错误做些什么return Promise.reject(error);});// 添加响应拦截器service.interceptors.response.use((response) => {// 对响应数据做点什么const res = response.data;const {status, data, message} = response || {};if (status !== 200) {const {message: messageErr} = service.interceptors.response.data || {};return Promise.reject(messageErr);} else {return {status, data};}},(error) => {const {data, status} = error.response || {};// 对响应错误做点什么 ...return Promise.reject(messageErr);});// 导出 axios 实例export default service;

使用时:

创建

import request from "../../utils/request";export function userlist(params) {  return request({    url: `/userlist`,    method: "GET",    params,  });}export function addUser(params) {  return request({    url: `/addUser`,    method: "POST",    data: {      ...params    }  });}

在组件中使用

import {deleteRoleApi} from '/@/api/...';deleteRoleApi(id).then(res => {})

安装vue-router

pnpm install vue-router --save

创建文件:src\router\index.ts

import { createRouter, createWebHashHistory } from 'vue-router'import type { RouteRecordRaw } from 'vue-router'import type { App } from 'vue'import { NO_RESET_WHITE_LIST } from '@/assets/constants'const Layout = () => import('@/layout/Layout.vue')export const constantRouterMap: AppRouteRecordRaw[] = [  {    path: '/',    component: Layout,    redirect: '/dashboard/analysis',    name: 'Root',    meta: {      hidden: true    }  },  {    path: '/login',    component: () => import('@/views/Login/Login.vue'),    name: 'Login',    meta: {      hidden: true,      noTagsView: true    }  },  {    path: '/personal',    component: Layout,    redirect: '/personal/personal-center',    name: 'Personal',    meta: {      hidden: true,      canTo: true    },    children: [      {        path: 'personal-center',        component: () => import('@/views/Personal/PersonalCenter/PersonalCenter.vue'),        name: 'PersonalCenter',        meta: {          hidden: true,          canTo: true        }      }    ]  },  {    path: '/404',    component: () => import('@/views/Error/404.vue'),    name: 'NoFind',    meta: {      hidden: true,      title: '404',      noTagsView: true    }  }]export const asyncRouterMap: AppRouteRecordRaw[] = [    {    path: '/error',    component: Layout,    redirect: '/error/404',    name: 'Error',    meta: {      icon: 'ci:error',      alwaysShow: true    },    children: [      {        path: '404-demo',        component: () => import('@/views/Error/404.vue'),        name: '404Demo',        meta: {          title: '404'        }      },      {        path: '403-demo',        component: () => import('@/views/Error/403.vue'),        name: '403Demo',        meta: {          title: '403'        }      },      {        path: '500-demo',        component: () => import('@/views/Error/500.vue'),        name: '500Demo',        meta: {          title: '500'        }      }    ]  },  ]const router = createRouter({  history: createWebHashHistory(),  strict: true,  routes: constantRouterMap as RouteRecordRaw[],  scrollBehavior: () => ({ left: 0, top: 0 })})export const resetRouter = (): void => {  router.getRoutes().forEach((route) => {    const { name } = route    if (name && !NO_RESET_WHITE_LIST.includes(name as string)) {      router.hasRoute(name) && router.removeRoute(name)    }  })}export const setupRouter = (app: App) => {  app.use(router)}export default router

挂载到vue

import { createApp } from 'vue'import '@/style.css'import App from '@/App.vue'import { setupStore } from '@/store'import { setupRouter } from '@/router'const app = createApp(App)setupStore(app)setupRouter(app)app.mount('#app')

安装scss

直接安装不需要node-sass 和 sass-loader

npm install -D sass

安装 按需加载 element plus

npm install element-plus
安装相关按需加载的插件
npm install -D unplugin-vue-components unplugin-auto-import unplugin-icons vite-plugin-style-import consola

vite.config.ts

import { defineConfig } from 'vite'import vue from '@vitejs/plugin-vue'import { fileURLToPath, URL } from 'node:url'import AutoImport from 'unplugin-auto-import/vite'import Components from 'unplugin-vue-components/vite'import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'import { FileSystemIconLoader } from 'unplugin-icons/loaders'import Icons from 'unplugin-icons/vite'import IconsResolver from 'unplugin-icons/resolver'import { createStyleImportPlugin, ElementPlusResolve } from 'vite-plugin-style-import'// https://vitejs.dev/config/export default defineConfig({  plugins: [    vue(),    AutoImport({      imports: ['vue', 'vue-router'], // 自动引入相关api      resolvers: [        ElementPlusResolver(),        IconsResolver({          // 设置自动导入的图标组件前缀          prefix: 'icon',          // 标识自定义图标集          customCollections: ['ci']        })      ],    }),    Components({      resolvers: [        ElementPlusResolver(),        IconsResolver({          // 设置自动导入的图标组件前缀          prefix: 'icon',          // 标识自定义图标集          customCollections: ['ci']        })      ],    }),    Icons({      compiler: 'vue3',      autoInstall: true,      // 自定义配置      customCollections: {         ci: FileSystemIconLoader('./src/assets/svg', svg => svg.replace(/^      resolves: [ElementPlusResolve()],      libs: [        {          libraryName: 'element-plus',          esModule: true,          resolveStyle: (name) = {            if (name === 'click-outside') {              return ''            }            return `element-plus/es/components/${name.replace(/^el-/, '')}/style/css`          }        }      ]    }),  ],  resolve: {    alias: {      '@': fileURLToPath(new URL('./src', import.meta.url))    }  },})

使用方式,直接用不需要import

import IconBaseline5g from '~icons/ep/edit'                                     ci: FileSystemIconLoader...) vue是自定义目录下的svg文件的名称 -->        

静态资源动态引用:图片

vite官方推荐

使用require的可以用上面的方法替换

@vitejs/plugin-legacy

安装

必须安装 Terser,因为插件遗留版使用 Terser 进行缩小。

npm i -D @vitejs/plugin-legacy terser
// vite.config.jsimport legacy from '@vitejs/plugin-legacy'export default {  plugins: [    legacy({      targets: ['defaults', 'not IE 11'],    }),  ],}

vite-plugin-compression 压缩大文件

安装

npm i -D vite-plugin-compression
import viteCompression from "vite-plugin-compression";plugins: [viteCompression({verbose: true,disable: false,deleteOriginFile: false,// 文件大于 100Kb 开启压缩 threshold: 100000,algorithm: "gzip",ext: "gz",}),],

压缩文件需要搭配nginx 配置,详情请点击

rollup-plugin-visualizer 这是一个依赖分析插件

参考链接:https://blog.csdn.net/g18204746769/article/details/127431733

安装

pnpm install vite-plugin-cdn-import --save-dev
import { visualizer } from 'rollup-plugin-visualizer';plugins: [visualizer()]

vite.config.js全部的配置

想了解配置想请点击

import { defineConfig, loadEnv } from 'vite'import vue from '@vitejs/plugin-vue'import { fileURLToPath, URL } from 'node:url'import AutoImport from 'unplugin-auto-import/vite'import Components from 'unplugin-vue-components/vite'import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'import { FileSystemIconLoader } from 'unplugin-icons/loaders'import Icons from 'unplugin-icons/vite'import IconsResolver from 'unplugin-icons/resolver'import { createStyleImportPlugin, ElementPlusResolve } from 'vite-plugin-style-import'import legacy from '@vitejs/plugin-legacy'import viteCompression from "vite-plugin-compression";// https://vitejs.dev/config/export default defineConfig((mode): any => {  const env = loadEnv(mode.mode, process.cwd())  return {    plugins: [      vue(),      AutoImport({        imports: ['vue', 'vue-router'], // 自动引入相关api        resolvers: [          ElementPlusResolver(),          IconsResolver({            // 设置自动导入的图标组件前缀            prefix: 'icon',            // 标识自定义图标集            customCollections: ['ci']          })        ],      }),      Components({        resolvers: [          ElementPlusResolver(),          IconsResolver({            // 设置自动导入的图标组件前缀            prefix: 'icon',            // 标识自定义图标集            customCollections: ['ci']          })        ],      }),      Icons({        compiler: 'vue3',        autoInstall: true,        // 自定义配置        customCollections: {           ci: FileSystemIconLoader('./src/assets/svg', svg => svg.replace(/^        resolves: [ElementPlusResolve()],        libs: [          {            libraryName: 'element-plus',            esModule: true,            resolveStyle: (name) = {              if (name === 'click-outside') {                return ''              }              return `element-plus/es/components/${name.replace(/^el-/, '')}/style/css`            }          }        ]      }),      legacy({        targets: ['defaults', 'not IE 11'],      }),      viteCompression({        verbose: true,        disable: false,        deleteOriginFile: false,        // 文件大于 100Kb 开启压缩         threshold: 100000,        algorithm: "gzip",        ext: "gz",      }),    ],    resolve: {      alias: {        '@': fileURLToPath(new URL('./src', import.meta.url))      }    },    server: {      host: '0.0.0.0',      port: env.VITE_PORT,      open: false,      proxy: {        '/api': {          target: 'https://gitee.com',          ws: true,          changeOrigin: true,          rewrite: (path:string) => path.replace(/^\/gitee/, ''),        },      },    },    build: {      outDir: 'dist',      chunkSizeWarningLimit: 1500,      rollupOptions: {        output: {          entryFileNames: `assets/[name].${new Date().getTime()}.js`,          chunkFileNames: `assets/[name].${new Date().getTime()}.js`,          assetFileNames: `assets/[name].${new Date().getTime()}.[ext]`,          compact: true,          // manualChunks: {          // vue: ['vue', 'vue-router', 'pinia'],          // echarts: ['echarts'],          // antvG6: ['@antv/g6'],          // elementPlus: ['element-plus'],          // },          manualChunks(id:string[]) {            // if (id.includes("style.css")) {            // // 需要单独分割那些资源 就写判断逻辑就行            // return 'src/style.css';            // }            // if (id.includes("HelloWorld.vue")) {            // // 单独分割hello world.vue文件            // return 'src/components/HelloWorld.vue';            // }            // // 最小化拆分包            if (id.includes('node_modules')) {              return id                .toString()                .split('node_modules/')[1]                .split('/')[0]                .toString()            }          },        },      },      minify: 'terser',      terserOptions: {        compress: {          drop_console: mode.mode === 'prd',          drop_debugger: mode.mode === 'prd',        },      },      sourcemap: mode.mode !== 'prd',    },    css: {      devSourcemap: true,      preprocessorOptions: { css: { charset: false } },    },  }})

找不到模块“@/xxx/xxx.vue”或其相应的类型声明。ts(2307)

配置tsconfig.json:确保你的tsconfig.json文件中包含了对.vue文件的支持。

{  "compilerOptions": {    "types": ["vue/vue3"] // 如果你使用的是Vue 3    // 或者 "types": ["vue/vue2"] 如果你使用的是Vue 2  }}

创建类型声明文件(如果自动处理不起作用):如果自动处理不起作用,你可以手动创建一个声明文件,例如shims-vue.d.ts,并在其中添加以下内容

declare module '*.vue' {  import type { DefineComponent } from 'vue'  const component: DefineComponent}, {}, any  export default component}

安装eslint && prettier

根据个人需求,我参考的这几个链接:

https://blog.csdn.net/m0_53022813/article/details/137379423

https://juejin.cn/post/7118294114734440455#heading-1

https://blog.csdn.net/weixin_43459866/article/details/124249172

https://blog.csdn.net/weixin_43993776/article/details/132564724

无法找到模块 vite-plugin-eslint 插件中的 TS 声明文件,隐式含有 “any” 类型。

vscode使用eslint

源码

上一篇:《GitHub新手入门指南:从零开始掌握基本用法》

下一篇:手机版腐蚀服务器怎么进去?