vite+vue3项目初始化搭建
"nodejs": v18.19.0
"pnpm": 8.15.0
"vue": v3.4.21
"vite": v5.2.0
1.创建项目
shell
pnpm create vite@latest
项目名字:gd_web
选择框架:Vue3
选择语言:JavaScript
进入项目:cd gd_web
安装依赖: pnpm i
启动项目:pnpm run dev
2.配置.editorconfig
# https://editorconfig.org
# 根目录配置,表示当前目录是编辑器配置的根目录
root = true
[*] # 对所有文件应用以下配置
charset = utf-8 # 使用 UTF-8 编码
indent_style = space # 使用空格进行缩进
indent_size = 4 # 每个缩进级别使用 4 个空格
end_of_line = lf # 使用 LF(Linux 和 macOS 的换行符)
insert_final_newline = true # 在文件末尾插入一行空白
trim_trailing_whitespace = true # 自动删除行末尾的空白字符
[*.md] # 对扩展名为 .md 的 Markdown 文件应用以下配置
insert_final_newline = false # 不在文件末尾插入一行空白
trim_trailing_whitespace = false # 不自动删除行末尾的空白字符
3.别名配置
在开发项目的时候文件与文件关系可能很复杂,因此我们需要给src文件夹配置一个别名!!!
在vite.config.js文件中:
javascript
import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
resolve: {
// 配置别名
alias: {
"@": path.resolve("./src") // 相对路径别名配置,使用 @ 代替 src
},
//extensions数组的意思是在import组件的时候自动补全.vue等文件后缀
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
}
})
如果不能识别path模块
shell
pnpm install @types/node --save-dev
配置完成后,我们发现我们 '@'之后没有提示,这个时候我们在根目录创建jsconfig.json
文件
json
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*": [
"src/*"
]
}
},
"exclude": [
"node_modules"
]
}
4.环境变量的配置
项目开发过程中,至少会经历开发环境、测试环境和生产环境(即正式环境)三个阶段。不同阶段请求的状态(如接口地址等)不尽相同,若手动切换接口地址是相当繁琐且易出错的。于是环境变量配置的需求就应运而生,我们只需做简单的配置,把环境状态切换的工作交给代码。
开发环境(development)
顾名思义,开发使用的环境,每位开发人员在自己的dev分支上干活,开发到一定程度,同事会合并代码,进行联调。
测试环境(testing)
测试同事干活的环境啦,一般会由测试同事自己来部署,然后在此环境进行测试
生产环境(production)
生产环境是指正式提供对外服务的,一般会关掉错误报告,打开错误日志。(正式提供给客户使用的环境。)
注意:一般情况下,一个环境对应一台服务器,也有的公司开发与测试环境是一台服务器!!!
项目根目录分别添加 开发、生产和测试环境的文件!
.env.development
.env.production
.env.test
文件内容:
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'development'
VITE_APP_TITLE = '项目名字'
VITE_APP_BASE_API = '/dev-api'
VITE_SERVE = 'http://127.0.0.1:8990'
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'production'
VITE_APP_TITLE = '项目名字'
VITE_APP_BASE_API = '/prod-api'
VITE_SERVE = 'http://127.0.0.1:8990'
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'test'
VITE_APP_TITLE = '项目名字'
VITE_APP_BASE_API = '/test-api'
VITE_SERVE = 'http://127.0.0.1:8990'
配置运行命令:package.json
"scripts": {
"dev": "pnpm vite --open",
"build:test": "pnpm vite build --mode test",
"build:pro": "pnpm vite build --mode production",
"preview": "vite preview"
},
通过import.meta.env获取环境变量
5.安装css预处理器sass
shell
pnpm install -D sass sass-loader
组件中使用:
javascript
<style scoped lang="scss"></style>
全局样式定义:
在src/styles目录下创建一个index.scss文件;
当然项目中需要用到清除默认样式,可以在index.scss引入reset.scss
reset.scss
scss
// reset.scss
// index.scss文件中引入
@import "reset.scss";
在入口文件中引入全局样式:
javascript
import '@/styles/index.scss'
在src/styles/index.scss全局样式文件中没有办法使用 变量 . 因此需要给项目中引入全局变量 变量.因此需要给项目中引入全局变量 变量.因此需要给项目中引入全局变量.
在style/variable.scss创建一个variable.scss文件!
在vite.config.js文件配置如下:
export default defineConfig((config) => {
//配置scss全局变量
css: {
preprocessorOptions: {
scss: {
javascriptEnabled: true,
additionalData: '@import "./src/styles/variable.scss";'
}
}
}
}
6.集成Element-plus
安装:
shell
pnpm install element-plus --save
配置自动导入: 需要安装unplugin-vue-components
和 unplugin-auto-import
这两款插件
shell
pnpm install -D unplugin-vue-components unplugin-auto-import
在vite配置文件中添加:
javascript
// vite.config.ts
import {defineConfig} from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import {ElementPlusResolver} from 'unplugin-vue-components/resolvers'
export default defineConfig({
// ...
plugins: [
// ...
AutoImport({
resolvers: [ElementPlusResolver()],
// 自动导入 Vue 相关函数,如:ref, reactive, toRef 等
imports: ['vue'],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
// ...
],
})
配置Element-plus 组件内容中文显示:
main.js文件中添加
javascript
// 引入element-plus样式
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import locale from 'element-plus/dist/locale/zh-cn.mjs'
app.use(ElementPlus, {locale})
Element-plus icon图标全局使用
shell
pnpm install @element-plus/icons-vue
注册所有图标,在component/index.js文件中
从 @element-plus/icons-vue 中导入所有图标并进行全局注册
javascript
// 引入element-plus提供的所有图标
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
// 对外暴露插件对象
export default {
// 必须叫做install方法,会有一个APP对象传参;
// 在入口文件引入使用,会自动执行该方法
install(app) {
// 将element-plus提供的图标注册为全局组件
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
},
}
在入口文件引入src/index.js文件,通过app.use方法安装自定义插件
javascript
// 注册全局组件
import gloablComponent from '@/components/index.js'
app.use(gloablComponent)
使用:详细见官网
html
<!-- 使用 el-icon 为 SVG 图标提供属性 -->
<template>
<div>
<el-icon :size="size" :color="color">
<Edit/>
</el-icon>
<!-- 或者独立使用它,不从父级获取属性 -->
<Edit/>
</div>
</template>
7.SVG图标配置
安装SVG依赖插件
pnpm install vite-plugin-svg-icons -D
在vite.config.js
中配置插件
javascript
plugins: [
// ...
// 配置自定义SVG 图标
createSvgIconsPlugin({
// Specify the icon folder to be cached
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
// Specify symbolId format
symbolId: 'icon-[dir]-[name]',
}),
// ...
]
入口文件(main.js)导入
javascript
// 注册SVG图标
import 'virtual:svg-icons-register'
将svg封装为全局组件
因为项目很多模块需要使用图标,因此把它封装为全局组件!!!
在src/components目录下创建一个SvgIcon组件:代表如下
vue
<template>
<div>
<svg :style="{ width: width, height: height }">
<use :xlink:href="prefix + name" :fill="color"></use>
</svg>
</div>
</template>
<script setup>
defineProps({
//xlink:href属性值的前缀
prefix: {
type: String,
default: '#icon-'
},
//svg矢量图的名字
name: String,
//svg图标的颜色
color: {
type: String,
default: ""
},
//svg宽度
width: {
type: String,
default: '16px'
},
//svg高度
height: {
type: String,
default: '16px'
}
})
</script>
<style scoped></style>
在src/components文件夹目录下创建一个index.js文件:用于注册components文件夹内部全部全局组件!!!
javascript
import SvgIcon from './SvgIcon'
const components = { SvgIcon }
// 引入element-plus提供的所有图标
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
// 对外暴露插件对象
export default {
// 必须叫做install方法,会有一个APP对象传参;
// 在入口文件引入使用,会自动执行该方法
install(app) {
//注册全局SVG组件
Object.keys(components).forEach((key) => {
app.component(key, components[key])
})
// 将element-plus提供的图标注册为全局组件
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
},
}
在入口文件引入src/index.js文件,通过app.use方法安装自定义插件
javascript
// 注册全局组件
import globalComponent from '@/components/index.js'
app.use(globalComponent)
8.配置封装axios
安装axios:
shell
pnpm install axios
在根目录下创建utils/request.js
javascript
import axios from "axios";
import {ElMessage} from "element-plus";
//创建axios实例
let request = axios.create({
baseURL: import.meta.env.VITE_APP_BASE_API,
timeout: 5000
})
//请求拦截器
request.interceptors.request.use(config => {
return config;
});
//响应拦截器
request.interceptors.response.use((response) => {
return response.data;
}, (error) => {
//处理网络错误
let msg = '';
let status = error.response.status;
switch (status) {
case 401:
msg = "token过期";
break;
case 403:
msg = '无权访问';
break;
case 404:
msg = "请求地址错误";
break;
case 500:
msg = "服务器出现问题";
break;
default:
msg = "无网络";
}
ElMessage({
type: 'error',
message: msg
})
return Promise.reject(error);
});
export default request;
9.api接口统一管理
在开发项目的时候,接口可能很多需要统一管理。在src目录下去创建api文件夹去统一管理项目的接口;
例如:
javascript
//统一管理用户相关的接口
import request from '../utils/request.js'
//项目用户相关的请求地址
const API = {
LOGIN_URL: '/admin/acl/index/login',
USERINFO_URL: '/admin/acl/index/info',
LOGOUT_URL: '/admin/acl/index/logout',
}
//登录接口
export const reqLogin = (data) => request.post(API.LOGIN_URL, data)
//获取用户信息
export const reqUserInfo = () => request.get(API.USERINFO_URL)
//退出登录
export const reqLogout = () => request.post(API.LOGOUT_URL)
10.配置vue-router
安装:
shell
pnpm install vue-router@4
1.创建src/router/index.js文件,使用路由懒加载,优化访问性能
javascript
import {createRouter, createWebHistory, createWebHashHistory} from 'vue-router'
const routes = [
{
path: '/',
name: 'Home',
component: () => import('../views/home.vue') // 建议进行路由懒加载,优化访问性能
},
{
path: '/about',
name: 'About',
component: () => import('../views/about.vue')
}
]
const router = createRouter({
// history: createWebHistory(), // 使用history模式
history: createWebHashHistory(), // 使用hash模式
routes
})
export default router
2.在App.vue 文件中使用router-view 组件,路由匹配到组件会通过router-view 组件进行渲染。
javascript
<template>
<div id="nav">
<router-link to="/">Home</router-link>
|
<router-link to="/about">About</router-link>
</div>
<router-view></router-view>
</template>
3.main.js中引入router
javascript
// ...
// 引入路由
import router from './router/index.js'
app.use(router)
// ...
11.配置pinia
安装:
shell
pnpm install pinia
在main.js文件中引入:
javascript
// 引入pinia
import {createPinia} from 'pinia'
app.use(createPinia())
创建文件夹src/stores
在该文件夹中管理一些公用数据,用户数据user.js,购物车数据等
定义
javascript
//定义关于counter的store
import {defineStore} from 'pinia'
/*defineStore 是需要传参数的,其中第一个参数是id,就是一个唯一的值,
简单点说就可以理解成是一个命名空间.
第二个参数就是一个对象,里面有三个模块需要处理,第一个是 state,
第二个是 getters,第三个是 actions。
*/
const useCounter = defineStore("counter", {
state: () => ({
count: 66,
}),
// getters 类似于 vue 里面的计算属性,可以对已有的数据进行修饰。
// 不管调用多少次,getters中的函数只会执行一次,且都会缓存。
getters: {},
actions: {}
})
//暴露这个useCounter模块
export default useCounter
使用
vue
<script setup>
// 首先需要引入一下我们刚刚创建的store
import useCounter from '../stores/counter.js'
// 因为是个方法,所以我们得调用一下
// 注意获取数据后不支持结构,结构则失去响应式
const counterStore = useCounter()
console.log(counterStore.count)
</script>
pinia提供了一个函数storeToRefs解决。引用官方API storeToRef 作用就是把结构的数据使用ref做代理
javascript
import {storeToRefs} from 'pinia'
const counterStore = useCounter()
// 结构仍为响应式数据
const {count} = storeToRefs(counterStore)
12.Proxy代理配置
javascript
import {defineConfig, loadEnv} from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import {ElementPlusResolver} from 'unplugin-vue-components/resolvers'
import {createSvgIconsPlugin} from 'vite-plugin-svg-icons'
// https://vitejs.dev/config/
export default defineConfig(({command, mode}) => {
// 根据当前工作目录中的 `mode` 加载 .env 文件
// 设置第三个参数为 '' 来加载所有环境变量,而不管是否有 `VITE_` 前缀。
const env = loadEnv(mode, process.cwd())
// console.log(env)
return {
base: env.VITE_USER_NODE_ENV === 'production' ? './' : '/',
plugins: [
vue(),
// 配置自定义SVG图标
createSvgIconsPlugin({
// Specify the icon folder to be cached
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
// Specify symbolId format
symbolId: 'icon-[dir]-[name]',
}),
// AutoImport({
// resolvers: [ElementPlusResolver()],
// // 自动导入 Vue 相关函数,如:ref, reactive, toRef 等
// imports: ['vue'],
// }),
// Components({
// resolvers: [ElementPlusResolver()],
// }),
],
resolve: {
// 配置别名
alias: {
"@": path.resolve("./src") // 相对路径别名配置,使用 @ 代替 src
},
//extensions数组的意思是在import组件的时候自动补全.vue等文件后缀
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
},
// 配置scss变量
css: {
preprocessorOptions: {
scss: {
javascriptEnabled: true,
additionalData: '@import "./src/styles/variable.scss";'
}
}
},
// 代理跨域
server: {
// open: true, //启动项目自动弹出浏览器
hmr: true, //开启热加载
host: false, //监听所有地址
port: 6688, //启动端口
strictPort: false, //设为 true 时若端口已被占用则会直接退出,而不是尝试下一个可用端口
https: false, // 是否开启https
//proxy: createProxy(env.VITE_APP_API_HOST),
proxy: {
[env.VITE_APP_BASE_API]: {
// 获取数据的服务器地址设置
target: env.VITE_SERVE,
//开启代理跨域
changeOrigin: true,
// secure:安全的
// 如果是https接口,需要配置这个参数
secure: false,
// 路径重写
// 将请求路径中的 '/api' 替换为 ''
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
}
})