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

本文主要是介绍vite + vue + typscript + pinia + axios + vue-router + elementPlus,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

npm create vite@latest

创建项目后

npm i
npm 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 pinia
npm 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<Element>) => {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?: stringtokenKey: stringtoken: stringroleRouters?: string[]rememberMe: booleanloginInfo?: 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},
})
在组件中使用
<script setup>
import {useUserStore} from '@/store/modules/user';
const store = useUserStore();
// ...
store.setTokenKey({...}); // 直接调用是不是很方便
// ...
store.user.page; // 直接获取
</script>
更多详细使用请点击此处

安装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}});
}

在组件中使用

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

安装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 } = routeif (name && !NO_RESET_WHITE_LIST.includes(name as string)) {router.hasRoute(name) && router.removeRoute(name)}})
}export const setupRouter = (app: App<Element>) => {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'], // 自动引入相关apiresolvers: [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(/^<svg /, '<svg fill="currentColor" '))}}),createStyleImportPlugin({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

<script setup>import IconBaseline5g from '~icons/ep/edit'</script><template><!-- 使用component 需要先引用 --><el-icon :size="20"><component :is="IconBaseline5g" /></el-icon><!--  直接使用,不需要引用 --><!-- icon是头部(上面vite.config.js 配置的prefix: 'icon'--><!-- ep是element plus图标库的简称 edit是图标的名字 --><el-icon :size="20"><iconEpEdit /></el-icon><!--  使用本地自定义的svg --><!-- icon是头部(上面vite.config.js 配置的prefix: 'icon'--><!-- Ci是自定义图标的集合(上面vite.config.js 配置的customCollections: { ci: FileSystemIconLoader...) vue是自定义目录下的svg文件的名称 --><el-icon :size="20"><iconCiVue /></el-icon>
</template>

静态资源动态引用:图片

vite官方推荐
使用require的可以用上面的方法替换

@vitejs/plugin-legacy

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

npm i -D @vitejs/plugin-legacy terser
// vite.config.js
import 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'], // 自动引入相关apiresolvers: [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(/^<svg /, '<svg fill="currentColor" '))}}),createStyleImportPlugin({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 } },},}
})

安装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

源码

这篇关于vite + vue + typscript + pinia + axios + vue-router + elementPlus的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/978775

相关文章

Knife4j+Axios+Redis前后端分离架构下的 API 管理与会话方案(最新推荐)

《Knife4j+Axios+Redis前后端分离架构下的API管理与会话方案(最新推荐)》本文主要介绍了Swagger与Knife4j的配置要点、前后端对接方法以及分布式Session实现原理,... 目录一、Swagger 与 Knife4j 的深度理解及配置要点Knife4j 配置关键要点1.Spri

前端如何通过nginx访问本地端口

《前端如何通过nginx访问本地端口》:本文主要介绍前端如何通过nginx访问本地端口的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、nginx安装1、下载(1)下载地址(2)系统选择(3)版本选择2、安装部署(1)解压(2)配置文件修改(3)启动(4)

HTML中meta标签的常见使用案例(示例详解)

《HTML中meta标签的常见使用案例(示例详解)》HTMLmeta标签用于提供文档元数据,涵盖字符编码、SEO优化、社交媒体集成、移动设备适配、浏览器控制及安全隐私设置,优化页面显示与搜索引擎索引... 目录html中meta标签的常见使用案例一、基础功能二、搜索引擎优化(seo)三、社交媒体集成四、移动

HTML input 标签示例详解

《HTMLinput标签示例详解》input标签主要用于接收用户的输入,随type属性值的不同,变换其具体功能,本文通过实例图文并茂的形式给大家介绍HTMLinput标签,感兴趣的朋友一... 目录通用属性输入框单行文本输入框 text密码输入框 password数字输入框 number电子邮件输入编程框

HTML img标签和超链接标签详细介绍

《HTMLimg标签和超链接标签详细介绍》:本文主要介绍了HTML中img标签的使用,包括src属性(指定图片路径)、相对/绝对路径区别、alt替代文本、title提示、宽高控制及边框设置等,详细内容请阅读本文,希望能对你有所帮助... 目录img 标签src 属性alt 属性title 属性width/h

CSS3打造的现代交互式登录界面详细实现过程

《CSS3打造的现代交互式登录界面详细实现过程》本文介绍CSS3和jQuery在登录界面设计中的应用,涵盖动画、选择器、自定义字体及盒模型技术,提升界面美观与交互性,同时优化性能和可访问性,感兴趣的朋... 目录1. css3用户登录界面设计概述1.1 用户界面设计的重要性1.2 CSS3的新特性与优势1.

HTML5 中的<button>标签用法和特征

《HTML5中的<button>标签用法和特征》在HTML5中,button标签用于定义一个可点击的按钮,它是创建交互式网页的重要元素之一,本文将深入解析HTML5中的button标签,详细介绍其属... 目录引言<button> 标签的基本用法<button> 标签的属性typevaluedisabled

HTML5实现的移动端购物车自动结算功能示例代码

《HTML5实现的移动端购物车自动结算功能示例代码》本文介绍HTML5实现移动端购物车自动结算,通过WebStorage、事件监听、DOM操作等技术,确保实时更新与数据同步,优化性能及无障碍性,提升用... 目录1. 移动端购物车自动结算概述2. 数据存储与状态保存机制2.1 浏览器端的数据存储方式2.1.

基于 HTML5 Canvas 实现图片旋转与下载功能(完整代码展示)

《基于HTML5Canvas实现图片旋转与下载功能(完整代码展示)》本文将深入剖析一段基于HTML5Canvas的代码,该代码实现了图片的旋转(90度和180度)以及旋转后图片的下载... 目录一、引言二、html 结构分析三、css 样式分析四、JavaScript 功能实现一、引言在 Web 开发中,

CSS place-items: center解析与用法详解

《CSSplace-items:center解析与用法详解》place-items:center;是一个强大的CSS简写属性,用于同时控制网格(Grid)和弹性盒(Flexbox)... place-items: center; 是一个强大的 css 简写属性,用于同时控制 网格(Grid) 和 弹性盒(F