使用vite构建vue3项目详细介绍(ts+pinia+sass+vue-router+axios+element-plus)

news2025/1/13 13:54:27

使用vite构建vue3项目详细介绍(ts+pinia+sass+vue-router+axios+element-plus)

1. 创建项目

npm init vite@latest

2. 配置 vite.config.ts

path需要安装--npm install @types/node --save-dev

import vue from '@vitejs/plugin-vue';
import { resolve } from 'path';
import { defineConfig, loadEnv, ConfigEnv } from 'vite';

const alias: Record<string, string> = {
	'@': resolve(__dirname, '.', './src') // 设置文件./src路径为 @
};

const viteConfig = defineConfig((mode: ConfigEnv) => {
	const env = loadEnv(mode.mode, process.cwd());
	return {
		plugins: [vue()],
		resolve: { alias },
	    base: mode.command === 'serve' ? './' : env.VITE_PUBLIC_PATH, // 打包路径
		server: {
			host: '0.0.0.0',
			port: env.VITE_PORT as unknown as number, // 服务端口号
			open: true, // 服务启动时是否自动打开浏览器
			hmr:true, // 开启热更新
		},
	};
});

export default viteConfig;

3. 配置 ts.config.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,
	  "baseUrl": "." /* 用于设置基础 url,可以帮我们省掉一些多余的路径前缀。 */,
	  "paths": {
		  "/@/*": ["src/*"]
	  } /* 将导入重新映射到相对于“baseUrl”的查找位置的一系列条目。 */,
	},
	"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
	"references": [{ "path": "./tsconfig.node.json" }]
  }
  

新建一个全局的ts文件声明.vue后缀文件 

 4. 配置使用 Sass

npm i sass -D

 5. 配置使用 vue-router

npm i vue-router

创建文件 src/router/route.ts

import { RouteRecordRaw } from 'vue-router';

/**
 * 建议:路由 path 路径与文件夹名称相同,找文件可浏览器地址找,方便定位文件位置
 *
 * 路由meta对象参数说明
 * meta: {
 *      title:          菜单栏及 tagsView 栏、菜单搜索名称(国际化)
 *      isLink:        是否超链接菜单,开启外链条件,`1、isLink: 链接地址不为空 2、isIframe:false`
 *      isHide:        是否隐藏此路由
 *      isKeepAlive:   是否缓存组件状态
 *      isAffix:       是否固定在 tagsView 栏上
 *      isIframe:      是否内嵌窗口,开启条件,`1、isIframe:true 2、isLink:链接地址不为空`
 *      roles:         当前路由权限标识,取角色管理。控制路由显示、隐藏。超级管理员:admin 普通角色:common
 *      icon:          菜单、tagsView 图标,阿里:加 `iconfont xxx`,fontawesome:加 `fa xxx`
 * }
 */

// 扩展 RouteMeta 接口
declare module 'vue-router' {
	interface RouteMeta {
		title?: string;
		isLink?: string;
		isHide?: boolean;
		isKeepAlive?: boolean;
		isAffix?: boolean;
		isIframe?: boolean;
		roles?: string[];
		icon?: string;
	}
}

/**
 * 定义动态路由
 * 前端添加路由,请在顶级节点的 `children 数组` 里添加
 * @description 未开启 isRequestRoutes 为 true 时使用(前端控制路由),开启时第一个顶级 children 的路由将被替换成接口请求回来的路由数据
 * @description 各字段请查看 `/@/views/system/menu/component/addMenu.vue 下的 ruleForm`
 * @returns 返回路由菜单数据
 */
export const dynamicRoutes: Array<RouteRecordRaw> = [
	{
		path: '/',
		name: '/',
		component: () => import('/@/layout/index.vue'),
		redirect: '/home',
		meta: {
			isKeepAlive: true,
		},
		children: [
			{
				path: '/home',
				name: 'home',
				component: () => import('/@/views/home/index.vue'),
				meta: {
					title: 'message.router.home',
					isLink: '',
					isHide: false,
					isKeepAlive: true,
					isAffix: true,
					isIframe: false,
					roles: ['admin', 'common'],
					icon: 'iconfont icon-shouye',
				},
			},
		],
	},
];

/**
 * 定义404、401界面
 * @link 参考:https://next.router.vuejs.org/zh/guide/essentials/history-mode.html#netlify
 */
export const notFoundAndNoPower = [
	{
		path: '/:path(.*)*',
		name: 'notFound',
		component: () => import('/@/views/error/404.vue'),
		meta: {
			title: 'message.staticRoutes.notFound',
			isHide: true,
		},
	},
	{
		path: '/401',
		name: 'noPower',
		component: () => import('/@/views/error/401.vue'),
		meta: {
			title: 'message.staticRoutes.noPower',
			isHide: true,
		},
	},
];

/**
 * 定义静态路由(默认路由)
 * 此路由不要动,前端添加路由的话,请在 `dynamicRoutes 数组` 中添加
 * @description 前端控制直接改 dynamicRoutes 中的路由,后端控制不需要修改,请求接口路由数据时,会覆盖 dynamicRoutes 第一个顶级 children 的内容(全屏,不包含 layout 中的路由出口)
 * @returns 返回路由菜单数据
 */
export const staticRoutes: Array<RouteRecordRaw> = [
	{
		path: '/login',
		name: 'login',
		component: () => import('/@/views/login/index.vue'),
		meta: {
			title: '登录',
		},
	},
];

创建文件src/router/index.ts

import { createRouter, createWebHashHistory } from 'vue-router';
import { staticRoutes, notFoundAndNoPower } from '/@/router/route';

/**
 * 创建一个可以被 Vue 应用程序使用的路由实例
 * @method createRouter(options: RouterOptions): Router
 * @link 参考:https://next.router.vuejs.org/zh/api/#createrouter
 */
export const router = createRouter({
	history: createWebHashHistory(),
	/**
	 * 说明:
	 * 1、notFoundAndNoPower 默认添加 404、401 界面,防止一直提示 No match found for location with path 'xxx'
	 * 2、backEnd.ts(后端控制路由)、frontEnd.ts(前端控制路由) 中也需要加 notFoundAndNoPower 404、401 界面。
	 *    防止 404、401 不在 layout 布局中,不设置的话,404、401 界面将全屏显示
	 */
	routes: [...notFoundAndNoPower, ...staticRoutes],
});

// 导出路由
export default router;

使用:在src/main.ts中导入并注册

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

createApp(App).use(router).mount('#app')

6. 配置使用 Pinia

npm install pinia

 

创建文件 src/stores/index.ts

// https://pinia.vuejs.org/
import { createPinia } from 'pinia';

// 创建
const pinia = createPinia();

// 导出
export default pinia;

创建文件 src/stores/userInfo.ts

import { defineStore } from 'pinia';
import Cookies from 'js-cookie';
import { Session } from '/@/utils/storage';

/**
 * 用户信息
 * @methods setUserInfos 设置用户信息
 */
export const useUserInfo = defineStore('userInfo', {
	state: (): UserInfosState => ({
		userInfos: {
			userName: '',
			photo: '',
			time: 0,
			roles: [],
			authBtnList: [],
		},
	}),
	actions: {
		async setUserInfos() {
			// 存储用户信息到浏览器缓存
			if (Session.get('userInfo')) {
				this.userInfos = Session.get('userInfo');
			} else {
				const userInfos: any = await this.getApiUserInfo();
				this.userInfos = userInfos;
			}
		},
		// 模拟接口数据
		async getApiUserInfo() {
			return new Promise((resolve) => {
				setTimeout(() => {
					// 模拟数据,请求接口时,记得删除多余代码及对应依赖的引入
					const userName = Cookies.get('userName');
					// 模拟数据
					let defaultRoles: Array<string> = [];
					let defaultAuthBtnList: Array<string> = [];
					// admin 页面权限标识,对应路由 meta.roles,用于控制路由的显示/隐藏
					let adminRoles: Array<string> = ['admin'];
					// admin 按钮权限标识
					let adminAuthBtnList: Array<string> = ['btn.add', 'btn.del', 'btn.edit', 'btn.link'];
					// test 页面权限标识,对应路由 meta.roles,用于控制路由的显示/隐藏
					let testRoles: Array<string> = ['common'];
					// test 按钮权限标识
					let testAuthBtnList: Array<string> = ['btn.add', 'btn.link'];
					// 不同用户模拟不同的用户权限
					if (userName === 'admin') {
						defaultRoles = adminRoles;
						defaultAuthBtnList = adminAuthBtnList;
					} else {
						defaultRoles = testRoles;
						defaultAuthBtnList = testAuthBtnList;
					}
					// 用户信息模拟数据
					const userInfos = {
						userName: userName,
						photo: 'https://img2.baidu.com/it/u=1978192862,2048448374&fm=253&fmt=auto&app=138&f=JPEG?w=504&h=500',
						time: new Date().getTime(),
						roles: defaultRoles,
						authBtnList: defaultAuthBtnList,
					};
					resolve(userInfos);
				}, 0);
			});
		},
	},
});

使用:在 src/main.ts中导入并注册

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import pinia from '/@/stores/index'

createApp(App).use(pinia).use(router).mount('#app')

7. 配置使用 Axios

npm i axios

创建文件 src/utils/request.ts

import axios, { AxiosInstance, AxiosRequestConfig } from 'axios'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Session } from '/@/utils/storage'
import qs from 'qs'

// 配置新建一个 axios 实例
const service: AxiosInstance = axios.create({
	baseURL: import.meta.env.VITE_API_URL,
	timeout: 50000,
	headers: { 'Content-Type': 'application/json' },
	paramsSerializer: {
		serialize(params) {
			return qs.stringify(params, { allowDots: true })
		},
	},
})

// 添加请求拦截器
service.interceptors.request.use(
	(config: AxiosRequestConfig) => {
		// 在发送请求之前做些什么 token
		if (Session.get('token')) {
			config.headers!['Authorization'] = `${Session.get('token')}`
		}
		return config
	},
	(error) => {
		// 对请求错误做些什么
		return Promise.reject(error)
	}
)

// 添加响应拦截器
service.interceptors.response.use(
	(response) => {
		// 对响应数据做点什么
		const res = response.data
		if (res.code && res.code !== 0) {
			// `token` 过期或者账号已在别处登录
			if (res.code === 401 || res.code === 4001) {
				Session.clear() // 清除浏览器全部临时缓存
				window.location.href = '/' // 去登录页
				ElMessageBox.alert('你已被登出,请重新登录', '提示', {})
					.then(() => {})
					.catch(() => {})
			}
			return Promise.reject(service.interceptors.response)
		} else {
			return response.data
		}
	},
	(error) => {
		// 对响应错误做点什么
		if (error.message.indexOf('timeout') != -1) {
			ElMessage.error('网络超时')
		} else if (error.message == 'Network Error') {
			ElMessage.error('网络连接错误')
		} else {
			if (error.response.data) ElMessage.error(error.response.statusText)
			else ElMessage.error('接口路径找不到')
		}
		return Promise.reject(error);
	}
);

// 导出 axios 实例
export default service

8. 配置使用 elementplus

npm i element-plus --save

使用:在 src/main.ts中导入并注册

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import pinia from '/@/stores/index'

import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

createApp(App).use(pinia).use(router).use(ElementPlus).mount('#app')

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/178922.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Jupyter的安装与默认目录的切换

下载与安装 清华大学开源软件镜像站 使用国内镜像下载更快&#xff0c;官网下载很慢 下载msi镜像文件&#xff0c;打开安装&#xff1a; 安装完成后得到4个文件 Reset Spyder...和Anaconda Powershell....都是相应的配置&#xff0c;其中后者是Jupyter和anaconda的dos命令窗口…

Coolify系列02-从0到1超详细手把手教你上手Coolify

重启 如果由于某种原因&#xff0c;你的实例崩溃了&#xff0c;你可以用下面的命令重新启动它: wget -q https://get.coollabs.io/coolify/install.sh \ -O install.sh; sudo bash ./install.sh -r防火墙设置 您需要在防火墙中允许以下端口 Coolify: 3000 (required)Revers…

【Mysql】Mysql的存储引擎

【Mysql】Mysql的存储引擎 文章目录【Mysql】Mysql的存储引擎1.概述2. 特点2.1 InnoDB2.2 MyISAM2.3 Memory2.4 区别3. 选择1.概述 **存储引擎&#xff1a;存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式。**存储引擎是基于表的&#xff0c;而不是 基于库的&…

HTTPS工作原理详解加密(TLS握手)过程

HTTPS概念 HTTPS就是一个有安全保障的HTTP通信&#xff0c;我们都知道&#xff0c;http是明文传输的&#xff0c;http报文是人肉眼就可识别的ASCII码&#xff0c;在通信过程中&#xff0c;http报文很容易被黑客窃听、篡改、伪造&#xff0c;而在互联网交易中&#xff0c;我们必…

【1】初识Linux

学习笔记目录 学习教程&#xff1a;B站 “黑马程序员” 初识Linux--入门Linux基础命令--会用Linux权限管控--懂权限Linux实用操作--熟练实战软件部署--深入掌握脚本&自动化--用的更强项目实战--学到经验云平台技术--紧跟潮流 操作系统概述 1.计算机由硬件和软件两个主要…

AcWing 12. 背包问题求具体方案

AcWing 12. 背包问题求具体方案AcWing 12. 背包问题求具体方案&#xff08;1&#xff09;问题&#xff08;2&#xff09;分析&#xff08;3&#xff09;代码AcWing 12. 背包问题求具体方案 &#xff08;1&#xff09;问题 &#xff08;2&#xff09;分析 我们先看一下这道题中…

tomcat更改默认端口

如下图把conf目录下的server.xml的下图所示处由原来的8080改为需要的即可&#xff1b;当前改为8087&#xff1b;保存之后重启tomcat&#xff1b; 网上一个资料说如果要运行2个tomcat&#xff0c;把下图的8009改为自己的&#xff0c;例如18009&#xff0c; 把下图的8005改为自己…

pythpon基础:创建文件索引升级版

需求环境 这是公司的一个需求&#xff0c;有一份很庞大的数据由好多视频文件组成&#xff0c;总共有12T左右&#xff0c;视频来源是一些下载的视频素材。每隔一段时间就要将一部分筛选好的视频文件剪切到server02服务器进行转码&#xff0c;筛选没被选中的文件将被删除。从下载…

5. 蒙特卡洛方法

蒙特卡洛方法5. 离轨策略5.1 策略评估&#xff08;基于重要度采样&#xff09;5.1.1 计算目标策略下的状态值5.1.2 蒙特卡洛算法&#xff08;状态值估计&#xff09;5.1.3 增量式的实现5.2 策略迭代5.3 减少重要性采样方差的方法5.3.1 折扣敏感的重要性采样5.3.2 每决策重要性抽…

go 语言 string 类型思考

string 作为 go 语言中的基础类型&#xff0c;其实有一些需要反复揣摩的&#xff0c;可能是我们使用的场景太简单&#xff0c;也可能是我们不需要那可怜的一点优化来提高性能&#xff0c;对它也就没那么上心了。 文章运行环境&#xff1a;go version go1.16.6 darwin/amd64 并…

浅析Java中的final关键字

一.final关键字的基本用法 在Java中&#xff0c;final关键字可以用来修饰类、方法和变量&#xff08;包括成员变量和局部变量&#xff09;。下面就从这三个方面来了解一下final关键字的基本用法。 1.修饰类 当用final修饰一个类时&#xff0c;表明这个类不能被继承。也就是说&a…

ACL访问控制的基本实例

典型案例&#xff1a; 配置需求∶ 在Router上部署基本ACL后&#xff0c;ACL将试图穿越Router的源地址为192.168.1.0/24网段的数据包过滤掉&#xff0c;并放行其他流量&#xff0c;从而禁止192.168.1.0/24网段的用户访问Router右侧的服务器网络。 配置&#xff1a; 1、Router已…

第三章 变量

一、数据类型&#xff08;P40&#xff09; 每一种数据都定义了明确的数据类型&#xff0c;在内存中分配了不同大小的内存空间(字节)。二、整数类型 整型的使用细节&#xff1a; &#xff08;1&#xff09;Java 各整数类型有固定的范围和字段长度&#xff0c;不受具体OS【操作系…

Java多线程(四)——ThreadPoolExecutor源码解析

ThreadPoolExecutor源码解析 多线程场景下&#xff0c;手动创建线程有许多缺点&#xff1a; 频繁创建、销毁线程会消耗大量 CPU 资源&#xff0c;销毁线程后需要被回收&#xff0c;对 GC 垃圾回收也有一定的压力 使用线程池有许多好处&#xff1a; 降低 CPU 资源消耗。通过…

Linux运维之解决服务器挖矿木马问题

文章目录1 挖矿木马1.1 定义1.2 挖矿特征1.3 解决挖矿木马1.3.1 阻断异常网络通信&#xff08;非必需&#xff09;1.3.2 清除定时任务1.3.3 清除启动项1.3.4 清除SSH公钥1.3.5 清除木马进程1.4 其他常见问题1.4.1 清除木马后又100%1.4.2 CPU占用100%却看不到进程1 挖矿木马 1.…

Python OS 文件目录方法 os.walk()

Python OS 文件/目录方法 os.walk() 概述 os.walk() 方法用于通过在目录树中游走输出在目录中的文件名&#xff0c;向上或者向下。 os.walk() 方法是一个简单易用的文件、目录遍历器&#xff0c;可以帮助我们高效的处理文件、目录方面的事情。 在Unix&#xff0c;Windows中…

BFS(三)腐烂的橘子(感染问题)

994. 腐烂的橘子 在给定的 m x n 网格 grid 中&#xff0c;每个单元格可以有以下三个值之一&#xff1a; 值 0 代表空单元格&#xff1b; 值 1 代表新鲜橘子&#xff1b; 值 2 代表腐烂的橘子。 每分钟&#xff0c;腐烂的橘子 周围 4 个方向上相邻 的…

领导看到我自用的IDEA插件,也回去悄悄安装了...

现在哪有程序员离得开 Idea 啊&#xff01;没有 Idea 的程序员那还有灵魂吗&#xff1f;那没有&#xff01;既然我们都用 Idea&#xff0c;如何提高 Idea 的开发效率&#xff0c;在开发工具上&#xff0c;我们就卷掉其他小伙伴呢&#xff01;今天鸡翅老哥就来给大家介绍几款我一…

函数的认识

文章目录 函数是什么库函数 自定义函数 函数参数 函数调用 函数的嵌套调用和链式访问 函数的声明和定义 函数递归一、函数是什么 维基百科中对函数的定义&#xff1a;子程序在计算机科学中&#xff0c;子程序&#xff08;英语&#xff1a;Subroutine, procedure, functio…

SpringBoot+Vue项目课程作业管理系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7/8.0 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.3.9 浏…