搭建Vue3后台管理系统模板
1、项目初始化
1.1 环境准备
- node v16+
查看node版本:node -v
- pnpm v9.7.0
查看pnpm版本:pnpm -v
1.2 初始化项目
本项目使用vite项目构建,vite官网:https://cn.vitejs.dev/guide/
pnpm:由npm/yarn衍生而来,解决了npm/yarn内部潜在的bug,极大的优化了性能,被誉为“最先进的包管理工具”
pnpm安装指令:
npm i -g pnpm
项目初始化命令:
pnpm create vite
输入项目名:project
选择框架:vue
选择语法:TypeScript
然后根据提示,切换目录,安装依赖,运行项目
cd project
pnpm install
pnpm run dev
项目成功启动:
2、项目配置
2.1 项目运行成功后浏览器自动打开
package.json:scripts——dev——“vite --open”
2.2 强制使用pnpm包管理工具
团队开发项目的时候,需要统一包管理器工具,因为不同包管理器工具下载同一个依赖,可能版本不一样,导致项目出现Bug问题,因此包管理器工具需要统一管理!!!
在根目录创建scripts/preinstall.js文件,添加下面的内容
if (!/pnpm/.test(process.env.npm_execpath || '')) {
console.warn(
`\u001b[33mThis repository must using pnpm as the package manager ` +
` for scripts to work peoperly.\u001b[39m\n`,
)
process.exit(1)
}
配置文件package.json:
"scripts": {
"preinstall": "node ./scripts/preinstall.js"
},
当我们使用npm或者yarn来安装包的时候,就会报错了。原理就是在install的时候会触发preinstall(npm提供的生命周期钩子)这个文件里的代码。
3、项目集成
3.1 集成element-plus
element-plus官网地址:http://element-plus.org/zh-CN/
安装:
pnpm install element-plus
pnpm install @element-plus/icons-vue
完整引入:
main.ts
import { createApp } from 'vue'
import App from './App.vue'
//引入element-plus插件与样式
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
//配置element-plus国际化
//@ts-ignore
import zhCn from 'element-plus/es/locale/lang/zh-cn'
//获取应用实例对象
const app = createApp(App)
//安装element-plus插件
app.use(ElementPlus, {
locale: zhCn,//element-plus国际化配置
})
//将应用挂载到挂载点上
app.mount('#app')
3.2 src别名的配置
在开发项目的时候文件与文件关系可能很复杂,因此我们需要给src文件夹配置一个别名。
vite.config.ts:
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
}
}
})
tsconfig.json:
{
"compilerOptions": {
"baseUrl": "./", //解析非相对模块的基地址,默认是当前目录
"paths": { //路径映射,相对于baseUrl
"@/*": [
"src/*"
]
}
}
}
3.3 环境变量的配置
项目开发过程中,至少会经历开发环境、测试环境和生产环境(即正式环境)三个阶段。不同阶段请求的状态(如接口地址等)不尽相同,若手动切换接口地址是相当繁琐且易出错的。于是环境变量配置的需求就应运而生,我们只需做简单的配置,把环境状态切换的工作交给代码。
项目根目录分别添加开发、测试和生产环境的文件!
- .env.development
# 变量必须以VITE_为前缀才能暴露给外部读取
NODE_ENV = 'development'
VITE_APP_TITLE = '开发环境平台'
VITE_APP_BASE_API = '/dev-api'
VITE_SERVE="http://xxx.com"
- .env.test
# 变量必须以VITE_为前缀才能暴露给外部读取
NODE_ENV = 'test'
VITE_APP_TITLE = '测试环境平台'
VITE_APP_BASE_API = '/dev-api'
VITE_SERVE="http://zzz.com"
- .env.production
# 变量必须以VITE_为前缀才能暴露给外部读取
NODE_ENV = 'production'
VITE_APP_TITLE = '生产环境平台'
VITE_APP_BASE_API = '/prod-api'
VITE_SERVE="http://yyy.com"
配置运行命令:
package.json:
{
"scripts": {
"dev": "vite --open",
"build:test": "vue-tsc && vite build --mode test",
"build:pro": "vue-tsc && vite build --mode production",
"preview": "vite preview"
},
}
通过import.meta.env获取环境变量
3.4 SVG图标配置
在开发项目的时候经常会用到svg矢量图,而且我们使用svg以后,页面上加载的不再是图片资源,这对页面性能来说是个很大的提升,而且我们svg文件比img要小的很多,放在项目中几乎不占用资源。
阿里图标地址:https://www.iconfont.cn/
安装svg依赖插件:
pnpm install vite-plugin-svg-icons -D
pnpm install fast-glob
在vite.config.ts中配置插件
import path from 'path'
//引入svg需要用到的插件
import { createSvgIconsPlugin } from "vite-plugin-svg-icons";
export default defineConfig({
plugins: [vue(),
createSvgIconsPlugin({
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
symbolId: 'icon-[dir]-[name]',
})
],
})
入口文件导入
main.ts:
import 'virtual:svg-icons-register'
使用:
1、封装一个全局的svg组件
src–components–svgIcon–index.vue
<template :style="width,height">
<!-- svg:图标外层容器节点,内部需要与use标签结合使用 -->
<svg>
<!-- xlink:href执行用哪一个图标,属性值务必#icon-图标名字 -->
<!-- use标签fill属性可以设置图标的颜色,前提是svg图标内不包含fill属性 -->
<use :xlink:href="prefix+name" :fill="color"></use>
</svg>
</template>
<script setup lang="ts">
//接收父组件传递过来的参数
defineProps({
//xlink:href属性值前缀
prefix:{
type:String,
default:'#icon-'
},
name:String,
color:{
type:String,
default:''
},
width:{
type:String,
default:'16px'
},
height:{
type:String,
default:'16px'
}
})
</script>
<style scoped>
</style>
2、全局注册
main.ts
import SvgIcon from '@/components/SvgIcon/index.vue'
app.component('SvgIcon',SvgIcon)
3、在别的组件中引入使用
<template>
<div>
<h1>SVG测试</h1>
<SvgIcon name="phone" color="yellow"></SvgIcon>
</div>
</template>
<script setup lang="ts">
</script>
<style scoped></style>
注:可使用自定义插件注册全局组件
全局组件有很多,使用自定义插件注册全局组件
1、1、封装一个全局的svg组件
src–components–svgIcon–index.vue
<template :style="width,height">
<!-- svg:图标外层容器节点,内部需要与use标签结合使用 -->
<svg>
<!-- xlink:href执行用哪一个图标,属性值务必#icon-图标名字 -->
<!-- use标签fill属性可以设置图标的颜色,前提是svg图标内不包含fill属性 -->
<use :xlink:href="prefix+name" :fill="color"></use>
</svg>
</template>
<script setup lang="ts">
//接收父组件传递过来的参数
defineProps({
//xlink:href属性值前缀
prefix:{
type:String,
default:'#icon-'
},
name:String,
color:{
type:String,
default:''
},
width:{
type:String,
default:'16px'
},
height:{
type:String,
default:'16px'
}
})
</script>
<style scoped>
</style>
2、创建自定义插件
src–components–index.ts
//引入项目中全部的全局组件
import SvgIcon from './svgIcon/index.vue'
const allGlobalComponent = {SvgIcon}
//对外暴露插件对象
export default{
install(app){
Object.keys(allGlobalComponent).forEach(key=>{
//注册为全局组件
app.component(key,allGlobalComponent[key]);
})
}
}
3、引入自定义插件并安装
main.ts
//引入自定义插件对象:注册整个项目全局组件
import globalComponent from '@/components'
//安装自定义插件
app.use(globalComponent)
4、在别的组件中引入使用
<template>
<div>
<h1>SVG测试</h1>
<SvgIcon name="phone" color="yellow"></SvgIcon>
</div>
</template>
<script setup lang="ts">
</script>
<style scoped></style>
3.5 集成Sass
1、安装sass和sass-loader
pnpm add sass sass-loader -D
2、清除默认样式,创建全局的样式文件
清除默认样式:
npm官网–reset.scss–code–reset.scss
src–styles–reset.scss
html {
-webkit-text-size-adjust: 100%
}
html:focus-within {
scroll-behavior: smooth
}
body {
-webkit-text-size-adjust: 100%;
-moz-text-size-adjust: 100%;
text-size-adjust: 100%;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
min-height: 100vh;
position: relative;
text-rendering: optimizeSpeed;
width: 100%
}
*,
:after,
:before {
box-sizing: border-box
}
a:not([class]) {
-webkit-text-decoration-skip: ink;
text-decoration-skip-ink: auto
}
a,
abbr,
acronym,
address,
applet,
article,
aside,
audio,
b,
big,
blockquote,
body,
canvas,
caption,
center,
cite,
code,
dd,
del,
details,
dfn,
div,
dl,
dt,
em,
embed,
fieldset,
figcaption,
figure,
footer,
form,
h1,
h2,
h3,
h4,
h5,
h6,
header,
hgroup,
html,
i,
iframe,
img,
ins,
kbd,
label,
legend,
li,
mark,
menu,
nav,
object,
ol,
output,
p,
pre,
q,
ruby,
s,
samp,
section,
small,
span,
strike,
strong,
sub,
summary,
sup,
table,
tbody,
td,
tfoot,
th,
thead,
time,
tr,
tt,
u,
ul,
var,
video {
border: 0;
font-size: 100%;
font: inherit;
margin: 0;
padding: 0;
vertical-align: baseline
}
:focus {
outline: 0
}
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
menu,
nav,
section {
display: block
}
ol,
ul {
list-style: none
}
blockquote,
q {
quotes: none
}
blockquote:after,
blockquote:before,
q:after,
q:before {
content: "";
content: none
}
input,
input:required {
box-shadow: none
}
input:-webkit-autofill,
input:-webkit-autofill:active,
input:-webkit-autofill:focus,
input:-webkit-autofill:hover {
-webkit-box-shadow: inset 0 0 0 30px #fff
}
input[type=search]::-webkit-search-cancel-button,
input[type=search]::-webkit-search-decoration,
input[type=search]::-webkit-search-results-button,
input[type=search]::-webkit-search-results-decoration {
-webkit-appearance: none;
-moz-appearance: none
}
input[type=search] {
-webkit-appearance: none;
-moz-appearance: none
}
input:focus {
outline: none
}
audio,
canvas,
video {
display: inline-block;
max-width: 100%
}
audio:not([controls]) {
display: none;
height: 0
}
[hidden] {
display: none
}
a:active,
a:hover {
outline: none
}
img {
height: auto;
max-width: 100%;
vertical-align: middle
}
img,
picture {
display: inline-block
}
button,
input {
line-height: normal
}
button,
html input[type=button],
input[type=reset],
input[type=submit] {
-webkit-appearance: button;
background: transparent;
border: 0;
cursor: pointer
}
button[disabled],
html input[disabled] {
cursor: default
}
[disabled] {
pointer-events: none
}
input[type=checkbox],
input[type=radio] {
padding: 0
}
input[type=search] {
-webkit-appearance: textfield;
box-sizing: content-box
}
input[type=search]::-webkit-search-cancel-button,
input[type=search]::-webkit-search-decoration {
-webkit-appearance: none
}
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0
}
button {
background: transparent;
border: 0
}
textarea {
overflow: auto;
resize: vertical;
vertical-align: top
}
table {
border-collapse: collapse;
border-spacing: 0;
text-indent: 0
}
hr {
background: #000;
border: 0;
box-sizing: content-box;
height: 1px;
line-height: 0;
margin: 0;
overflow: visible;
padding: 0;
page-break-after: always;
width: 100%
}
pre {
font-family: monospace, monospace;
font-size: 100%
}
a {
background-color: transparent
}
abbr[title] {
border-bottom: none;
text-decoration: none
}
code,
kbd,
pre,
samp {
font-family: monospace, monospace
}
small,
sub,
sup {
font-size: 75%
}
sub,
sup {
line-height: 0;
position: relative;
vertical-align: baseline
}
sub {
bottom: -5px
}
sup {
top: -5px
}
button,
input,
optgroup,
select,
textarea {
font-family: inherit;
font-size: 100%;
line-height: 1;
margin: 0;
padding: 0
}
button,
input {
overflow: visible
}
button,
select {
text-transform: none
}
[type=button],
[type=reset],
[type=submit],
button {
-webkit-appearance: button
}
[type=button]::-moz-focus-inner,
[type=reset]::-moz-focus-inner,
[type=submit]::-moz-focus-inner,
button::-moz-focus-inner {
border-style: none;
outline: 0;
padding: 0
}
legend {
border: 0;
color: inherit;
display: block;
max-width: 100%;
white-space: normal;
width: 100%
}
fieldset {
min-width: 0
}
body:not(:-moz-handler-blocked) fieldset {
display: block
}
progress {
vertical-align: baseline
}
[type=number]::-webkit-inner-spin-button,
[type=number]::-webkit-outer-spin-button {
height: auto
}
[type=search] {
-webkit-appearance: textfield;
outline-offset: -2px
}
[type=search]::-webkit-search-decoration {
-webkit-appearance: none
}
::-webkit-file-upload-button {
-webkit-appearance: button;
font: inherit
}
summary {
display: list-item
}
template {
display: none
}
创建全局的样式文件:
src–styles–index.scss
//引入清除默认样式
@import './reset.scss'
3、引入模板的全局样式
main.ts
//引入模板的全局样式
import '@/styles/index.scss'
4、引入全局变量$
src–styles–variable.scss
//项目提供scss全局变量
//之后样式的全局变量可以写在这
vite.config.ts
export default defineConfig({
css:{
preprocessorOptions:{
scss:{
javascriptEnabled:true,
additionalData:'@import "./src/styles/variable.scss";',
}
}
}
})
配置完scss提供的全局变量就可以在组件中使用了
5、组件内使用scss语法:
<style scoped lang="scss">
</style>