You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

295 lines
14 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 15 | 实战痛点1复杂Vue项目的规范和基础库封装
你好我是大圣欢迎进入课程的第15讲。
在全家桶实战篇的前几讲里我们学习了Vue 3本身的进阶内容。从今天开始我们尝试着把这些技能都用在实际项目中聊一下实战中常见的痛点。不过既然是实际项目那还是有很多库需要引入的比如网络请求时用到的axios、时间处理时用到的Dayjs等等。今天我要跟你聊的则是复杂 Vue 项目的规范和基础库的封装。
## 组件库
在项目开发中我们首先需要一个组件库帮助我们快速搭建项目组件库提供了各式各样的封装完备的组件。现在社区可选择的组件库有element-plus、antd-vueNaive-UI、Element3等我们选择Element3来搭建项目首先我们来到项目目录下执行下面的代码安装Element3。
```bash
npm install element3 --save
```
然后我们在src/main.js中使用一下Element3。看下面的代码我们在其中引入了Element3和主体对应的CSS并使用use(Element3)加载组件库。
```javascript
import { createApp } from 'vue'
import Element3 from 'element3'
import 'element3/lib/theme-chalk/index.css'
import store from './store/index'
import App from './App.vue'
import router from './router/index'
const app = createApp(App)
app.use(store)
.use(router)
.use(Element3)
.mount('#app')
```
这样项目的入口页面就注册好了Element3内置的组件。关于Element3的组件列表你可以到[Element3官网](https://e3.shengxinjing.cn/#/component/installation)查看。接下来,我们就可以使用组件库去搭建我们的页面了。
首先我们打开项目目录下的src/App.vue文件把之前的学习清单应用时的测试代码移除然后新增下面的代码。你能看到我们在代码中使用Element3的[Container布局组件](https://e3.shengxinjing.cn/#/component/container)实现管理系统的整体布局。
```xml
<template>
<el-container>
<el-header>Header</el-header>
<el-container>
<el-aside width="200px">
<div>
<router-link to="/"> Home</router-link>
</div>
<div>
<router-link to="/about">About</router-link>
</div>
</el-aside>
<el-container>
<el-main>
<router-view></router-view>
</el-main>
</el-container>
</el-container>
</el-container>
</template>
<script setup>
</script>
<style>
.el-header,
.el-footer {
background-color: #b3c0d1;
color: #333;
text-align: center;
}
.el-aside {
background-color: #d3dce6;
color: #333;
}
.el-main {
background-color: #e9eef3;
color: #333;
}
body > .el-container {
margin-bottom: 40px;
}
</style>
```
上面代码对应在前端的显示格局如下代码上方的Header组件承载着页面的头部信息包括项目左上角的名字、右上角的用户信息、消息等等。代码中的aside对应了前端页面左侧的侧边栏承载着页面主要的导航信息main组件内部使用router-view渲染路由对应的组件然后我们继续使用Element3逐渐丰富Header和导航信息。
## ![图片](https://static001.geekbang.org/resource/image/d2/2a/d237cyycfb6d9c10aa7a04dc5073852a.png?wh=1920x539)
在Element3中我们也可以很方便地找出我们需要的组件就像Menu等等。在下面的代码中我们使用el-menu组件渲染header组件el-menu内部使用el-ment-item渲染导航组件。
```xml
<el-header>
<el-menu
:default-active="1"
class="el-menu-demo"
mode="horizontal"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b"
>
<el-menu-item index="1">处理中心</el-menu-item>
<el-submenu index="2">
<template v-slot:title>我的工作台</template>
<el-menu-item index="2-1">选项1</el-menu-item>
<el-menu-item index="2-2">选项2</el-menu-item>
<el-menu-item index="2-3">选项3</el-menu-item>
<el-submenu index="2-4">
<template v-slot:title>选项4</template>
<el-menu-item index="2-4-1">选项1</el-menu-item>
<el-menu-item index="2-4-2">选项2</el-menu-item>
<el-menu-item index="2-4-3">选项3</el-menu-item>
</el-submenu>
</el-submenu>
<el-menu-item index="3" disabled>消息中心</el-menu-item>
<el-menu-item index="4"
><a href="https://element3-ui.com" target="_blank"
>订单管理</a
></el-menu-item
>
</el-menu>
</el-header>
```
使用menu组件渲染header和aslide组件后页面布局示意图如下这样页面的基本结构就搭建完毕了。
## ![图片](https://static001.geekbang.org/resource/image/59/7a/59d3d065f3aec7b769341b10da49407a.png?wh=1816x752)
## 工具库
完成页面基本结构的搭建后在我们获取后端数据时需要使用axios发起网络请求。在项目的根目录下打开命令行执行下面的命令这样我们就可以安装axios了axios 跟 Vue 版本没有直接关系,安装最新即可)。
```bash
npm i axios --save
```
axios作为现在最流行的网络请求库可以直接使用axios.get或者axios.post去获取数据。但是在项目开发中业务逻辑有很多配置需要进行统一设置**所以安装完axios之后我们需要做的就是封装项目中的业务逻辑**。
首先在项目在登录成功之后后端会返回一个token用来存储用户的加密信息我们把token放在每一次的http请求的header中后端在收到请求之后会对请求header中的token进行认证然后解密出用户的信息过期时间并且查询用户的权限后校验完毕才会返回对应的数据。
所以我们要对所有的http请求进行统一拦截确保在请求发出之前从本地存储中获取token这样就不需要在每个发起请求的组件内去读取本地存储。后端数据如果出错的话接口还要进行统一拦截比如接口返回的错误是登录状态过期那么就需要提示用户跳转到登录页面重新登录。
这样我们就把网络接口中需要统一处理的内容都放在了拦截器中统一处理了。在下面的代码中所有接口在请求发出之前都会使用getToken获取token然后放在header中。在接口返回报错信息的时候会在调试窗口统一打印报错信息。在项目的组件中我们只需要直接使用封装好的axios即可。
```javascript
import axios from 'axios'
import { useMsgbox, Message } from 'element3'
import store from '@/store'
import { getToken } from '@/utils/auth'
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
timeout: 5000, // request timeout
})
service.interceptors.request.use(
config => {
if (store.getters.token) {
config.headers['X-Token'] = getToken()
}
return config
},
error => {
console.log(error) // for debug
return Promise.reject(error)
},
)
service.interceptors.response.use(
response => {
const res = response.data
if (res.code !== 20000) {
console.log('接口信息报错',res.message)
return Promise.reject(new Error(res.message || 'Error'))
} else {
return res
}
},
error => {
console.log('接口信息报错' + error)
return Promise.reject(error)
},
)
export default service
```
然后我们在项目里集成CSS预编译器CSS预编译器可以帮我们更快、更高效地管理和编写CSS代码。在这里我们选择Sass作为CSS预处理语言然后我们就进入项目根目录下执行下面代码安装Sass。
```bash
npm install -D sass
```
然后我们进入src/components/Todolist.vue文件中。看下面的代码我们直接在style标签上新增 lang=“scss”这样就可以使用Sass的语法了。有了Sass之后我们在CSS里使用了变量、嵌套、继承等逻辑并定义了$padding和$white这两个变量。这样我们就可以嵌套书写CSS选择器也就极大地提高我们写CSS的效率。
```xml
<style lang="scss" scoped>
$padding:10px;
$white:#fff;
ul {
width:500px;
margin:0 auto;
padding: 0;
li {
&:hover {
cursor: pointer;
}
list-style-type: none;
margin-bottom: $padding;
padding: $padding;
background: $white;
box-shadow: 1px 3px 5px rgba(0, 0, 0, 0.1);
}
}
</style>
```
Sass让我们在CSS的世界里也拥有了编程的概念在实际项目中可以使用变量和函数等概念优化CSS代码这个你在Element3组件库的实现中也能看到。
在Element3的[GitHub项目](https://github.com/hug-sun/element3/tree/master/packages/element3/packages/theme-chalk/src)中我们可以看到所有的Sass代码。以common/var.scss文件为例在这个文件中我们可以看到Element3中所有的变量并且这个文件中的代码也对颜色、动画函数、边框字体大小等等都做了统一的设置。
我们也可以修改这些变量从而获得一个定制风格的Element3。所以项目在开始之初我们就可以想一下整体设计风格最好能够预先定义好整体的颜色边框字体大小等等这能极大降低后续的css维护成本。
至此,一个基于 Vite + Vue 3 + Vue Router + Vuex + Element3 + Axios + Sass 的前端项目开发环境搭建完毕。下面,我们来打磨一下这个项目。**简单来说,就是给项目增加代码规范约束、提交规范约束等,让其更完善、更健壮。**
## 代码规范和提交规范
由于个人习惯的不同每个人写代码的风格也略有不同。比如在写JavaScript代码中有些人习惯在每行代码之后都写分号有些人习惯不写分号。但是团队产出的项目就需要有一致的风格这样代码在团队之间阅读起来时也会更加流畅。ESLint就是专门用来做规范团队代码的一个库。
首先我们安装ESLint进入到项目文件夹使用下面的命令我们就可以在全局或者本地安装ESLint了。
```bash
npm i eslint -D
```
ESLint 安装成功后,在项目根目录下执行 npx eslint --init然后按照终端操作的提示完成一系列设置来创建配置文件。你可以按照下图所示的选择来始化ESLint。
![图片](https://static001.geekbang.org/resource/image/45/c0/457e448ee27c431f51ebb525ff1c87c0.png?wh=1258x422)
我们设置的是比较松散的校验规则你可以根据团队风格去额外配置ESLint的插件。我们进入到项目目录下的eslintrc.json中在rules中新增下面代码也就是强制要求JavaScript的行尾不写分号。
```json
"rules": {
"semi": ["warn","never"]
}
```
然后我们在命令行中执行npx eslint src接着你就会看到下图所示的报错信息其中详细告诉你了哪里的代码不合规范。根据报错信息的提示我们进入到router/index.js文件后删掉第15行代码结束的分号就可以解除这个警告。
![图片](https://static001.geekbang.org/resource/image/08/c0/087yyf6fce41ededfd59ed39883281c0.png?wh=1480x258)
前面我们已经统一了代码规范,并且在提交代码时进行强约束来保证仓库代码的质量。多人协作的项目中,在提交代码这个环节,也存在一种情况:不能保证每个人对提交信息的准确描述,因此会出现提交信息紊乱、风格不一致的情况。
对于这种情况一种比较好的解决方案是在执行git commit命令的时候同时执行ESLint。我们使用husky管理git的钩子函数在每次代码提交至git之前去执行ESLint只有ESLint的校验通过commit才能执行成功。后面的进阶开发篇中单元测试也会放在git的钩子函数中执行确保提交到git中的代码都是测试通过的。
项目代码符合规范后我们就可以把代码提交到代码仓库中git允许我们在每次提交时附带一个提交信息作为说明。我们在项目根目录执行下面的命令提交了一个附带信息是commit的代码。
```bash
git add .
git commit -m 'init commit'
```
**然后我们需要再定义一下git的提交规范描述信息精准的git提交日志会让我们在后期维护和 处理Bug时有据可查**。在项目开发周期内,我们还可以根据规范的提交信息,快速生成开发日志,从而方便我们追踪项目和把控进度。 如下图所示我们可以看到Vue 3的代码提交日志。
![图片](https://static001.geekbang.org/resource/image/44/5b/44cfecd1b31deb36b918bd7aa0c9a05b.png?wh=1920x1287)
看了Vue 3代码日志提交的格式初次接触的你可能会觉得复杂。其实不然Vue 3在代码日志中使用的是【类别: 信息】的格式我们可以通过类别清晰地知道这次提交是代码修复还是功能开发feat。冒号后面的信息是用来解释此次提交的内容在修复bug时还会带上issue中的编号。在现在的项目开发中我们也会强制要求使用和Vue 3一样的git 日志格式。
## 总结
今天这一讲的内容到这就结束了我们来复习一下今天学到的内容。首先我们引入了Element3组件库在项目入口注册Element3后你可以在项目的任意地方直接使用[Element3首页的组件列表](https://e3.shengxinjing.cn/#/component/installation)。
这样我们就可以很方便地使用layout和container布局实现页面的搭建然后引入axios作为网络请求库并且对接口统一做了全局拦截。下一讲中项目权限管理也是在axios拦截函数里实现的。
当然复杂的Vue项目更需要良好的规范毕竟没有规矩不成方圆为此我们进一步规范了代码格式使用ESLint统一JavaScript的代码风格husky管理git的钩子函数并且规定了git的提交日志格式确保代码的可维护性。
## 思考题
关于Element3组件库布局和导航组件的使用你有什么其他布局的建议呢
欢迎在留言区发表你的看法,也欢迎你把这一讲的内容推荐给你的同事和朋友们,我们下一讲再见。