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

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

【 html+css 绚丽Loading 】000046 三才归元阵

前言:哈喽,大家好,今天给大家分享html+css 绚丽Loading!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、信息💡1.简介:💡2.外观描述:💡3.使用方式:💡4.战斗方式:💡5.提升:💡6.传说: 📚三、源代码,上代码,可以直接复制使用🎥效果🗂️目录✍️

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

Vue3项目开发——新闻发布管理系统(六)

文章目录 八、首页设计开发1、页面设计2、登录访问拦截实现3、用户基本信息显示①封装用户基本信息获取接口②用户基本信息存储③用户基本信息调用④用户基本信息动态渲染 4、退出功能实现①注册点击事件②添加退出功能③数据清理 5、代码下载 八、首页设计开发 登录成功后,系统就进入了首页。接下来,也就进行首页的开发了。 1、页面设计 系统页面主要分为三部分,左侧为系统的菜单栏,右侧

【VUE】跨域问题的概念,以及解决方法。

目录 1.跨域概念 2.解决方法 2.1 配置网络请求代理 2.2 使用@CrossOrigin 注解 2.3 通过配置文件实现跨域 2.4 添加 CorsWebFilter 来解决跨域问题 1.跨域概念 跨域问题是由于浏览器实施了同源策略,该策略要求请求的域名、协议和端口必须与提供资源的服务相同。如果不相同,则需要服务器显式地允许这种跨域请求。一般在springbo

HTML提交表单给python

python 代码 from flask import Flask, request, render_template, redirect, url_forapp = Flask(__name__)@app.route('/')def form():# 渲染表单页面return render_template('./index.html')@app.route('/submit_form',

Java 后端接口入参 - 联合前端VUE 使用AES完成入参出参加密解密

加密效果: 解密后的数据就是正常数据: 后端:使用的是spring-cloud框架,在gateway模块进行操作 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.0-jre</version></dependency> 编写一个AES加密

vue2 组件通信

props + emits props:用于接收父组件传递给子组件的数据。可以定义期望从父组件接收的数据结构和类型。‘子组件不可更改该数据’emits:用于定义组件可以向父组件发出的事件。这允许父组件监听子组件的事件并作出响应。(比如数据更新) props检查属性 属性名类型描述默认值typeFunction指定 prop 应该是什么类型,如 String, Number, Boolean,