项目搭建规范
一 代码规范
1.1. 集成editorconfig配置
EditorConfig 有助于为不同 IDE 编辑器上处理同一项目的多个开发人员维护一致的编码风格。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
root = true
[*] charset = utf-8 indent_style = space indent_size = 2 end_of_line = lf trim_trailing_whitespace = true insert_final_newline = true
[*.md] max_line_length = off trim_trailing_whitespace = false
|
VSCode需要安装一个插件:EditorConfig for VS Code
1.2. 使用prettier工具
Prettier 是一款强大的代码格式化工具,支持 JavaScript、TypeScript、CSS、SCSS、Less、JSX、Angular、Vue、GraphQL、JSON、Markdown 等语言,基本上前端能用到的文件格式它都可以搞定,是当下最流行的代码格式化工具。
1.安装prettier
2.配置.prettierrc文件:
- useTabs:使用tab缩进还是空格缩进,选择false;
- tabWidth:tab是空格的情况下,是几个空格,选择2个;
- printWidth:当行字符的长度,推荐80,也有人喜欢100或者120;
- singleQuote:使用单引号还是双引号,选择true,使用单引号;
- trailingComma:在多行输入的尾逗号是否添加,设置为
none
;
- semi:语句末尾是否要加分号,默认值true,选择false表示不加;
1 2 3 4 5 6 7 8
| { "useTabs": false, "tabWidth": 2, "printWidth": 80, "singleQuote": true, "trailingComma": "none", "semi": false }
|
3.创建.prettierignore忽略文件
1 2 3 4 5 6 7 8 9
| /dist/* .local .output.js /node_modules/**
**/*.svg **/*.sh
/public/*
|
4.VSCode需要安装prettier的插件
5.测试prettier是否生效
- 测试一:在代码中保存代码;
- 测试二:配置一次性修改的命令;
在package.json中配置一个scripts:
1
| "prettier": "prettier --write ."
|
1.3. 使用ESLint检测
1.在前面创建项目的时候,我们就选择了ESLint,所以Vue会默认帮助我们配置需要的ESLint环境。
2.VSCode需要安装ESLint插件:
3.解决eslint和prettier冲突的问题:
安装插件:(vue在创建项目时,如果选择prettier,那么这两个插件会自动安装)
1
| yarn add eslint-plugin-prettier eslint-config-prettier -D
|
添加prettier插件:
1 2 3 4 5 6 7 8
| extends: [ "plugin:vue/vue3-essential", "eslint:recommended", "@vue/typescript/recommended", "@vue/prettier", "@vue/prettier/@typescript-eslint", 'plugin:prettier/recommended' ],
|
1.4. git Husky和eslint
虽然我们已经要求项目使用eslint了,但是不能保证组员提交代码之前都将eslint中的问题解决掉了:
那么如何做到这一点呢?可以通过Husky工具:
- husky是一个git hook工具,可以帮助我们触发git提交的各个阶段:pre-commit、commit-msg、pre-push
如何使用husky呢?
这里我们可以使用自动配置命令:
1
| npx husky-init && npm install
|
这里会做三件事:
1.安装husky相关的依赖:
2.在项目目录下创建 .husky
文件夹:
3.在package.json中添加一个脚本:
接下来,我们需要去完成一个操作:在进行commit时,执行lint脚本:
这个时候我们执行git commit的时候会自动对代码进行lint校验。
1.5. git commit规范
1.5.1. 代码提交风格
通常我们的git commit会按照统一的风格来提交,这样可以快速定位每次提交的内容,方便之后对版本进行控制。
但是如果每次手动来编写这些是比较麻烦的事情,我们可以使用一个工具:Commitizen
- Commitizen 是一个帮助我们编写规范 commit message 的工具;
1.安装Commitizen
2.安装git-cz:
并且在package.json中添加scripts:
这个时候我们提交代码需要使用 yarn commit
:
Type |
作用 |
feat |
新增特性 (feature) |
fix |
修复 Bug(bug fix) |
docs |
修改文档 (documentation) |
style |
代码格式修改(white-space, formatting, missing semi colons, etc) |
refactor |
代码重构(refactor) |
perf |
改善性能(A code change that improves performance) |
test |
测试(when adding missing tests) |
build |
变更项目构建或外部依赖(例如 scopes: webpack、gulp、npm 等) |
ci |
更改持续集成软件的配置文件和 package 中的 scripts 命令,例如 scopes: Travis, Circle 等 |
chore |
变更构建流程或辅助工具(比如更改测试环境) |
revert |
代码回退 |
我们也可以在scripts中构建一个命令来执行 cz:
1.5.2. 自己配置 提交规则
新建一个changelog.config.js 格式如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| module.exports = { disableEmoji: false, list: [ 'test', 'feat', 'fix', 'chore', 'api', 'docs', 'refactor', 'style', 'ci', 'perf', 'merge' ], maxMessageLength: 64, minMessageLength: 3, questions: [ 'type', 'scope', 'subject', 'body', 'breaking', 'issues', 'lerna' ], scopes: [], types: { api: { description: 'api 接口对接', emoji: '🅰️', value: 'api' }, merge: { description: '分支合并', emoji: '🙏', value: 'merge' }, chore: { description: '构建过程或辅助工具更改', emoji: '🤖', value: 'chore' }, ci: { description: '更改持续集成软件的配置文件和package中的scripts命令,例如scopes: Travis, Circle等', emoji: '🎡', value: 'ci' }, docs: { description: '文档变更', emoji: '✏️', value: 'docs' }, feat: { description: '新增一个功能', emoji: '🎸', value: 'feat' }, fix: { description: '修复一个Bug', emoji: '🐛', value: 'fix' }, perf: { description: '优化性能', emoji: '⚡️', value: 'perf' }, refactor: { description: '代码重构', emoji: '💡', value: 'refactor' }, style: { description: '代码格式(不影响功能,例如空格、分号等格式修正)', emoji: '💄', value: 'style' }, test: { description: '测试', emoji: '💍', value: 'test' } } }
|
1.5.3. 代码提交验证
如果我们按照cz来规范了提交风格,但是依然有同事通过 git commit
按照不规范的格式提交应该怎么办呢?
1.安装 @commitlint/config-conventional 和 @commitlint/cli
1
| npm i @commitlint/config-conventional @commitlint/cli -D
|
2.在根目录创建commitlint.config.js文件,配置commitlint
1 2 3
| module.exports = { extends: ['@commitlint/config-conventional'] }
|
3.使用husky生成commit-msg文件,验证提交信息:
1
| npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"
|
二 第三方库集成
2.1. vue.config.js配置
vue.config.js有三种配置方式:
- 方式一:直接通过CLI提供给我们的选项来配置:
- 比如publicPath:配置应用程序部署的子目录(默认是
/
,相当于部署在 https://www.my-app.com/
);
- 比如outputDir:修改输出的文件夹;
- 方式二:通过configureWebpack修改webpack的配置:
- 可以是一个对象,直接会被合并;
- 可以是一个函数,会接收一个config,可以通过config来修改配置;
- 方式三:通过chainWebpack修改webpack的配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| const path = require('path')
module.exports = { outputDir: './build', chainWebpack: (config) => { config.resolve.alias.set('@', path.resolve(__dirname, 'src')).set('views', '@/views') } }
|
2.2. vue-router集成
安装vue-router的最新版本:
1
| npm install vue-router@next
|
创建router对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import { createRouter, createWebHashHistory } from 'vue-router' import { RouteRecordRaw } from 'vue-router'
const routes: RouteRecordRaw[] = [ { path: '/', redirect: '/main' }, { path: '/main', component: () => import('../views/main/main.vue') }, { path: '/login', component: () => import('../views/login/login.vue') } ]
const router = createRouter({ routes, history: createWebHashHistory() })
export default router
|
安装router:
1 2 3
| import router from './router'
createApp(App).use(router).mount('#app')
|
在App.vue中配置跳转:
1 2 3 4 5 6 7
| <template> <div id="app"> <router-link to="/login">登录</router-link> <router-link to="/main">首页</router-link> <router-view></router-view> </div> </template>
|
2.3. vuex集成
安装vuex:
创建store对象:
1 2 3 4 5 6 7 8 9 10 11
| import { createStore } from 'vuex'
const store = createStore({ state() { return { name: 'coderwhy' } } })
export default store
|
安装store:
1
| createApp(App).use(router).use(store).mount('#app')
|
在App.vue中使用:
1
| <h2>{{ $store.state.name }}</h2>
|
2.4. element-plus集成
Element Plus,一套为开发者、设计师和产品经理准备的基于 Vue 3.0 的桌面端组件库:
- 相信很多同学在Vue2中都使用过element-ui,而element-plus正是element-ui针对于vue3开发的一个UI组件库;
- 它的使用方式和很多其他的组件库是一样的,所以学会element-plus,其他类似于ant-design-vue、NaiveUI、VantUI都是差不多的;
安装element-plus
1
| npm install element-plus
|
2.4.1. 全局引入
一种引入element-plus的方式是全局引入,代表的含义是所有的组件和插件都会被自动注册:
1 2 3 4 5 6 7
| import ElementPlus from 'element-plus' import 'element-plus/lib/theme-chalk/index.css'
import router from './router' import store from './store'
createApp(App).use(router).use(store).use(ElementPlus).mount('#app')
|
2.4.2. 局部引入
也就是在开发中用到某个组件对某个组件进行引入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| <template> <div id="app"> <router-link to="/login">登录</router-link> <router-link to="/main">首页</router-link> <router-view></router-view>
<h2>{{ $store.state.name }}</h2>
<el-button>默认按钮</el-button> <el-button type="primary">主要按钮</el-button> <el-button type="success">成功按钮</el-button> <el-button type="info">信息按钮</el-button> <el-button type="warning">警告按钮</el-button> <el-button type="danger">危险按钮</el-button> </div> </template>
<script lang="ts"> import { defineComponent } from 'vue'
import { ElButton } from 'element-plus'
export default defineComponent({ name: 'App', components: { ElButton } }) </script>
<style lang="less"> </style>
|
但是我们会发现是没有对应的样式的,引入样式有两种方式:
- 全局引用样式(像之前做的那样);
- 局部引用样式(通过babel的插件);
1.安装babel的插件:
1
| npm install babel-plugin-import -D
|
2.配置babel.config.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| module.exports = { plugins: [ [ 'import', { libraryName: 'element-plus', customStyleName: (name) => { return `element-plus/lib/theme-chalk/${name}.css` } } ] ], presets: ['@vue/cli-plugin-babel/preset'] }
|
但是这里依然有个弊端:
- 这些组件我们在多个页面或者组件中使用的时候,都需要导入并且在components中进行注册;
- 所以我们可以将它们在全局注册一次;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import { ElButton, ElTable, ElAlert, ElAside, ElAutocomplete, ElAvatar, ElBacktop, ElBadge, } from 'element-plus'
const app = createApp(App)
const components = [ ElButton, ElTable, ElAlert, ElAside, ElAutocomplete, ElAvatar, ElBacktop, ElBadge ]
for (const cpn of components) { app.component(cpn.name, cpn) }
|
2.5. axios集成
安装axios:
简单封装axios:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| import axios from 'axios' import type { AxiosRequestConfig } from 'axios'
import { BASE_URL, TIME_OUT } from './config'
const instance = axios.create({ baseURL: BASE_URL, timeout: TIME_OUT })
instance.interceptors.request.use( (config) => {
window.localStorage.getItem('CS_TOKEN') ? (config.headers.token = window.localStorage.getItem('CS_TOKEN')) : '' return config }, (err) => { console.log('request error:', err) } )
instance.interceptors.response.use( (res) => { return res.data }, (err) => { return Promise.reject(err.message) } )
export function request<T>(config: AxiosRequestConfig): Promise<T> { return new Promise((resolve, reject) => { instance(config) .then((res) => { resolve(res.data) }) .catch((err) => { reject(err) }) }) }
|
2.5.1 使用方法
1 2 3 4 5 6 7 8 9 10 11 12 13
| import { request } from '@/utils//request'
interface LoginDataType { code: string, message: string, data: any | [] } export function login(): Promise<LoginDataType> { return request<LoginDataType>({ url: '/home/multidata', method: 'GET' }) }
|
1 2 3 4 5 6 7 8 9
| import { login } from '@/api/login'
login() .then((res) => { console.log(res) }) .catch((err) => { console.log(err) })
|