文章目录
- 1. 项目初始化
- 1.1 项目目录结构
- 1.2 相关组件列表
- 1.3 创建项目
- 2. 重置样式表
- 3.设置路径别名
- 4. 设置环境变量
- 5.状态存储(Pinia)
- 5.1 安装插件
- 5.2 配置
- 5.3 用户信息案例
- 5.3.1 状态存储设置
- 5.3.2 使用用户信息
- 6. 路由设置(Router)
- 6.1 安装路由插件
- 6.2 配置路由
- 7. 安装element-plus
- 8. 网络请求设置
- 8.1 安装
- 8.1 网络请求封装
- 8.2 封装API
- 9.跨域处理
- 10. rem适配(移动端)
1. 项目初始化
1.1 项目目录结构
完整的项目目录结构如下:
1.2 相关组件列表
# 状态存储
pnpm i pinia -S
# 状态存储持久化(可选)
pnpm i pinia-plugin-persistedstate
# 路由
pnpm i vue-router
# 安装内置node,用于path别名设置
pnpm i -D @types/node
# API
pnpm i @vueuse/core -S
# 网络请求
pnpm i axios -S
# 动画(可选)
pnpm i animate.css
# UI
pnpm i element-plus
pnpm i @element-plus/icons-vue
# 样式
pnpm i less
pnpm i -D sass
# (可选)
pnpm i moment
# 原子化样式(可选)
pnpm i unocss
1.3 创建项目
使用pnpm创建vite项目。
pnpm create vite
#输入项目名
Project name: vue3-template
# 选择前端框架
Select a framework: Vue
# 选择语言
Select a variant: Typescript
安装和启动:
cd vitedemo
pnpm install
pnpm run dev
2. 重置样式表
reset.css和normalize.css可以都放到src/assets/css/目录下
PC端:reset.css
@charset "utf-8";
/* CSS Document */
* { color:#444; }
body { font:12px/1.5 "微软雅黑",Arial,Tahoma, Helvetica,\5b8b\4f53, sans-serif; }
html,body,div,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,object,code,em,span,var,legend,button,input,textarea,th,td,a,img,header,footer,nav,aside,audio,datalist,section { margin:0;padding:0;border:0;outline:0; }/*清除内外边距*/
h1,h2,h3,h4,h5,h6 { font-weight:normal;font-size:100%; }/*设置默认字体*/
:focus { outline:0; }
ul,ol,ul li,ol li { list-style: none; }/*重置列表*/
address,caption,cite,em,code,dfn,th,var { font-style:normal;font-weight:normal; }
form label { cursor:pointer; }
input,button,select,textarea { font-family:inherit;font-size:100%;outline:none; }
textarea { resize:none }
input { vertical-align:middle; }
img { border:0; }/*重置图片元素*/
table { border-collapse:collapse;border-spacing: 0; }/*重置表格*/
.l { float:left; }
.r { float:right; }
button,input[type="reset"],input[type="button"],input[type="submit"] { line-height:normal !important; }
a { text-decoration:none;}
a { color:#666;}
a:hover { text-decoration:underline; }
input { _filter:chroma(color=#000000); }
/*--清除浮动
------------------------------------------------------------------------------------------*/
.clearfix:after { clear:both;content:".";display:block;font-size:0;height:0;visibility:hidden; }
.clearfix:after { _zoom:1; }
.overflow { overflow:hidden; _zoom:1; }
.clear { clear:both; height:0;font-size:0; overflow:hidden; }
APP端:normalize.css
Normalize.css 使浏览器呈现所有 HTML 元素更加一致,并且符合现代 web 标准。
Normalize.css 只作用于需要规范化的样式。
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in iOS.
*/
html {
line-height: 1.15; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers.
*/
body {
margin: 0;
}
/**
* Render the `main` element consistently in IE.
*/
main {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* Remove the gray background on active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Remove the border on images inside links in IE 10.
*/
img {
border-style: none;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input { /* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select { /* 1 */
text-transform: none;
}
/**
* Correct the inability to style clickable types in iOS and Safari.
*/
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
vertical-align: baseline;
}
/**
* Remove the default vertical scrollbar in IE 10+.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in Edge, IE 10+, and Firefox.
*/
details {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Misc
========================================================================== */
/**
* Add the correct display in IE 10+.
*/
template {
display: none;
}
/**
* Add the correct display in IE 10.
*/
[hidden] {
display: none;
}
3.设置路径别名
项目别名配置的时候需要用的 path 模块,而path模块是node.js的内置模块,node不支持TS。
(1) 所以在配置别名的时候,需要先执行 pnpm i -D @types/node
(2) 然后修改文件vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
//引入path模块
import {resolve} from "path"
// https://vitejs.dev/config/
export default defineConfig({
//配置别名
resolve:{
alias:{
'@': resolve(__dirname,"src"),
'~': resolve(__dirname,"src")
}
},
plugins: [vue()],
})
(3) 再修改tsconfig.json
在compilerOptions中添加下面配置:
/*别名配置*/
"baseUrl": "./",
"paths": {
"@/*":["src/*"],
}
引入组件示例:
4. 设置环境变量
环境变量,可以根据不同的配置不同的参数值。比如开发环境、测试环境、生产环境都使用不同的服务器IP地址。
所以通过切换不同的环境变量,满足不同的场景需求。
在**项目根目录(通常是src目录外面)**新建.env.development和.env.production两个文件。
.env.development
NODE_ENV = 'development'
# 以VITE开头
VITE_BASE_API = "http://localhost:56518"
VITE_BASE_URL='https://csdnvip.blog.csdn.net/'
.env.production
NODE_ENV = 'production'
# 以VITE开头
VITE_BASE_API = "http://localhost:11111"
VITE_BASE_URL='https://csdnvip.blog.csdn.net/'
如果两个文件(.env.development和.env.production)在src文件夹里面,那么可以通过在vite.config.ts文件中设置envDir的值为"./src",
这样,这两个文件也可以生效。
在package.json中的scripts配置不同的场景模式:
"dev": "vite --mode development",
"prod": "vite --mode production",
为了在代码中获取用户自定义环境变量的TypeScript智能提示,还需要在根目录新建env.d.ts文件:
//可以在在代码中获取用户自定义环境变量的TypeScript智能提示
interface ImportMetaEnv {
readonly VITE_BASE_API: string
// 更多环境变量 ...
}
interface ImportMeta {
readonly env: ImportMetaEnv
}
验证环境变量取值:
在App.vue中打印环境变量:
<template>
<router-view></router-view>
</template>
<script setup lang='ts'>
console.log(import.meta.env.NODE_ENV)
console.log(import.meta.env.VITE_BASE_API)
console.log(import.meta.env.VITE_BASE_URL)
</script>
<style scoped>
</style>
由于启动时,使用的是pnpm run dev
模式启动,所以读取到的是.env.development文件中的值。
可以看到VITE_BASE_API和VITE_BASE_URL的值都打印出来了,但是NODE_ENV的值并没有显示出来。
这是由于默认只能读取VITE前缀的变量的值。
如果需要读取其他前缀的变量的值,可以在vite.config.ts文件中添加以下配置:
//读取下列前缀开头的变量,注意这里也要把VITE加入进去,否则VITE开头的读取不到
envPrefix: ["VITE_","APP_","NODE_"],
5.状态存储(Pinia)
5.1 安装插件
# 安装pinia,用于状态存储
pnpm i pinia -S
# 安装pinia插件,用于状态存储持久化
pnpm i pinia-plugin-persistedstate -S
5.2 配置
# 引入插件
import {createPinia} from "pinia"
import {createPersistedState} from "pinia-plugin-persistedstate"
# 全局配置
const pinia = createPinia()
app.use(pinia)
# pinia的持久化全局配置
pinia.use(createPersistedState({
storage: localStorage,
key: id => `__persisted__${id}`, //指定key的设置
auto: true
}))
5.3 用户信息案例
5.3.1 状态存储设置
创建状态存储的文件夹src/store
创建保存用户信息的文件src/store/user.ts用来存储用户信息。
useUserStore是约定俗成的规则,useXXXXStore规则。
import { defineStore } from "pinia"
export const useUserStore = defineStore({
id: "user",
state: () => {
return {
token: "",
userInfo: {}
}
},
//方法
actions: {
setUserInfo(data: any) {
this.token = data.token
this.userInfo = data.user_info
}
}
})
5.3.2 使用用户信息
6. 路由设置(Router)
6.1 安装路由插件
pnpm i vue-router -S
创建路由的文件夹src/router
6.2 配置路由
(1) 配置路由包
在main.ts中
import router from "@/router"
app.use(router)
(2) 配置路由规则
在/src/router/index.ts中
//createRouter:用于创建vue-router实例对象
//RouteRecordRaw: 用于规范,路由规则,增加路由对象类型限制
//createWebHistory
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router"
//创建路由规则
const routes: Array<RouteRecordRaw> = [
{
path: "/",
component: () => import("@/views/index.vue"),
},
{
path: "/login",
component: () => import("@/views/public/login/index.vue"),
children: []
}
]
//创建路由实例
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: routes
})
//路由导航守卫
import { useUserStore } from "@/store/user"
router.beforeEach((to, from, next) => {
const user = useUserStore()
if (user.token) {
next()
} else {
// router.push({ path: "/" })
console.log("未登录")
}
})
export default router
7. 安装element-plus
安装element插件
pnpm i element-plus
pnpm i @element-plus/icons-vue
安装自动导入插件
pnpm install -D unplugin-vue-components unplugin-auto-import
修改vite.config.ts
//自动导入组件以及样式
//注意unplugin-auto-import后面是vite
const AutoImport = require('unplugin-auto-import/vite');
const Components = require('unplugin-vue-components/vite');
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers');
然后在plugins中添加:
AutoImport({
resolvers: [ElementPlusResolver()]
}),
Components({
resolvers: [ElementPlusResolver()]
})
更新后的完整内容如下:
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from "path"
//自动导入组件以及样式
const AutoImport = require('unplugin-auto-import/vite');
const Components = require('unplugin-vue-components/vite');
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers');
// https://vitejs.dev/config/
export default defineConfig({
base: process.env.ELECTRON == "true" ? './' : "./",
plugins: [
vue(),
//自动导入组件
AutoImport({
resolvers: [ElementPlusResolver()]
}),
Components({
resolvers: [ElementPlusResolver()]
})
],
resolve: {
alias: {
"@": resolve(__dirname, "src")
}
}
})
修改main.ts,引入样式和导入图标库
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
图标库需要遍历加入app的组件.
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
完整的main.ts如下:
import { createApp } from 'vue'
import '@/assets/css/reset.css'
import App from './App.vue'
import router from "@/router"
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
const app = createApp(App)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
app.use(router)
app.mount('#app')
这样在使用element-plus的组件的时候,就不需要再额外导入了。
8. 网络请求设置
8.1 安装
# Api插件
pnpm i @vueuse/core -S
# 网络请求
pnpm i axios -S
创建/src/util/request.ts
8.1 网络请求封装
import { useUserStore } from "@/store/user"
import axios from "axios"
import {ElMessage} from "element-plus"
const service = axios.create({
baseURL: "/api", //请求的基础路径设置
timeout: 10000
})
//请求拦截器
service.interceptors.request.use((config) => {
const userStore = useUserStore()
if(userStore.token){
config.headers.token = userStore.token
}
return config
},(error) => {
return Promise.reject(error)
})
//响应拦截器
service.interceptors.response.use((response) => {
return response.data
},(error) =>{
// let status = error.response.status
ElMessage.error(error.message)
return Promise.reject(new Error(error.message))
})
export default service
8.2 封装API
封装api,在api中使用上面的request.ts中封装的网络请求。
新建文件src/api/user.ts
,用来请求用户信息
import request from "@/utils/request"
//get
export const getUser = (data:any) =>{
return request({
url:"user/list",
method:"get",
params:data
})
}
//post
export const editUser = (data:any) =>{
return request({
url:"user/edit",
method:"post",
params:data
})
}
9.跨域处理
修改vite.config.ts
//跨域代理设置
server: {
port: 8002,
//允许跨域
cors: true,
//遇到api开头的,自动替换为target对应的地址请求
proxy: {
'/api': { //注意:这里的api要和request.ts中的baseURL保持一致
target: "http://xxxx.com",
changeOrigin: true
}
}
},
10. rem适配(移动端)
如果是移动端开发,需要配置该项,PC端不需要。
创建 /src/utils/rem.ts