一、 使用脚手架创建Vue3项目的相关选项
二、代码规范
1.1 集成 .editorconfig 配置
EditorConfig有助于为不同IDE编辑器上处理同一项目的多个开发人员维护一致的编码风格。
# https://editorconfig.org
root = true
[*] # 表示所有文件适用
charset = utf-8 # 字符集
indent_style = space # 缩进风格(tab | space)
indent_size = 2 # 缩进大小
end_of_line = lf # 控制换行类型(lf | cr | crlf)
insert_final_newline = true # 去除行首的任意空白字符
trim_trailing_whitespace = true # 始终在文件末尾插入一个新行
# 仅有 md 文件适用以下规则
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false
vscode需要安装下面的插件以使EditorConfig生效。
1.2 使用prettier工具
Prettier是一款强大的代码格式化工具,支持JavaScript、TypeScript、CSS、SCSS、Less、JSX、Angular、Vue、GraphQL、JSON、Markdown等语言,基本上前端用到的文件格式它都可以搞定,是当下最流行的代码格式化工具。
1、安装prettier
npm install prettier -D
2、配置.prettierrc文件:
- tabWidth:tab缩进大小,默认为2
- useTabs:使用tab缩进,默认false(空格)
- semi:使用分号, 默认true
- singleQuote:使用单引号, 默认false(在jsx中配置无效, 默认都是双引号)
- printWidth:每一行代码长度,常用为80、100、120
- TrailingCooma:行尾逗号,默认none,可选 none|es5|all,es5 包括es5中的数组、对象,all 包括函数对象等所有可选
- arrowParens:箭头函数参数括号,默认avoid 可选 avoid| always,avoid 能省略括号的时候就省略 例如x => x, always 总是有括号
{
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": false,
"printWidth": 80,
"TrailingCooma": "none",
"arrowParens": "always"
}
3、配置.prettierignore忽略文件
/dist/*
.local/dist
.output.js
/node_modules/**
**/*.svg
**/*.sh
/public/*
vscode需要安装prettier插件
1.3 使用ESLint检测
使用脚手架创建Vue项目时,如果选择ESLint,Vue会默认帮助我们配置需要的ESLint环境,并且解决eslint和prettier的冲突。
1.4 git Husky和eslint
通过Husky,可以在执行git commit命令的时候对其进行校验,如果不符合eslint规范,那么会自动通过规范进行修复。
husky自动配置命令:
npx husky-init && npm install
1.5 git commit规范
1.5.1 使用Commitizen 编写规范的 commit message
1.安装Commitizen
npm install commitizen -D
2.安装cz-conventional-changelog,并且初始化cz-conventional-changelog:
npx commitizen init cz-conventional-changelog --save-dev --save-exact
这个时候我们提交代码需要使用 npx cz:
- 第一步是选择type,本次更新的类型
| 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 | 代码回退 |
- 第二步选择本次修改的范围(作用域)
- 第三步选择提交的信息
- 第四步提交详细的描述信息
- 第五步是否是一次重大的更改
- 第六步是否影响某个open issue
我们也可以在scripts中构建一个命令来执行 cz
提交时运行
npm run commit
1.5.2 用commitlint进行代码提交验证
对 git commit 按照规范的格式进行验证,不符合规范时拒绝提交。
- 我们可以通过commitlint来限制提交;
1.安装 @commitlint/config-conventional 和 @commitlint/cli
npm i @commitlint/config-conventional @commitlint/cli -D
2.在根目录创建commitlint.config.js文件,配置commitlint
module.exports = {
extends: ['@commitlint/config-conventional']
}
3.使用husky生成commit-msg文件,验证提交信息:
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:修改输出的文件夹;
- 比如publicPath:配置应用程序部署的子目录(默认是
- 方式二:通过configureWebpack修改webpack的配置:
- 可以是一个对象,直接会被合并;
- 可以是一个函数,会接收一个config,可以通过config来修改配置;
- 方式三:通过chainWebpack修改webpack的配置:
- 是一个函数,会接收一个基于 webpack-chain 的config对象,可以对配置进行修改;
const { defineConfig } = require("@vue/cli-service");
const path = require('path')
module.exports = defineConfig({
outputDir: './build',
// configureWebpack: {
// resolve: {
// alias: {
// views: '@/views'
// }
// }
// }
// configureWebpack: (config) => {
// config.resolve.alias = {
// '@': path.resolve(__dirname, 'src'),
// views: '@/views'
// }
// },
chainWebpack: (config) => {
config.resolve.alias.set('@', path.resolve(__dirname, 'src')).set('views', '@/views')
}
});
2.2. 使用vue-router最新版
安装vue-router的最新版本:
npm install vue-router@next
2.3. 使用vuex最新版
安装vuex最新版本:
npm install vuex@next
2.4. element-plus集成
Element Plus,一套为开发者、设计师和产品经理准备的基于 Vue 3.0 的桌面端组件库:
- 它的使用方式和很多其他的组件库是一样的,所以学会element-plus,其他类似于ant-design-vue、NaiveUI、VantUI(移动端)都是差不多的;
安装element-plus
npm install element-plus
2.4.1. 全局引入
一种引入element-plus的方式是全局引入,代表的含义是所有的组件和插件都会被自动注册:
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. 局部引入
首先你需要安装unplugin-vue-components 和 unplugin-auto-import这两款插件
npm install -D unplugin-vue-components unplugin-auto-import
然后把下列代码插入到你的 Vite 或 Webpack 的配置文件中
Vite
// vite.config.ts
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default {
plugins: [
// ...
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
}
Webpack
// webpack.config.js
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
module.exports = {
// ...
plugins: [
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
}
想了解更多打包 (Rollup, Vue CLI) 和配置工具,请参考 unplugin-vue-components 和 unplugin-auto-import。
2.5. axios集成
安装axios:
npm install axios
封装axios:
import axios, { AxiosResponse, AxiosInstance, AxiosRequestConfig } from "axios";
import { ElLoading } from "element-plus";
interface InterceptorHooks {
requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig;
requestInterceptorCatch?: (error: any) => any;
responseInterceptor?: (response: AxiosResponse) => AxiosResponse;
responseInterceptorCatch?: (error: any) => any;
}
interface RequestConfig extends AxiosRequestConfig {
showLoading?: boolean;
interceptorHooks?: InterceptorHooks;
}
interface Data<T> {
data: T;
returnCode: string;
success: boolean;
}
class AxiosRequest {
config: AxiosRequestConfig;
interceptorHooks?: InterceptorHooks;
showLoading: boolean;
loading?: any;
instance: AxiosInstance;
constructor(options: RequestConfig) {
this.config = options;
this.interceptorHooks = options.interceptorHooks;
this.showLoading = options.showLoading ?? true;
this.instance = axios.create(options);
this.setupInterceptor();
}
setupInterceptor(): void {
this.instance.interceptors.request.use(
this.interceptorHooks?.requestInterceptor,
this.interceptorHooks?.requestInterceptorCatch
);
this.instance.interceptors.response.use(
this.interceptorHooks?.responseInterceptor,
this.interceptorHooks?.requestInterceptorCatch
);
this.instance.interceptors.request.use((config) => {
if (this.showLoading) {
this.loading = ElLoading.service({
lock: true,
text: "Loading",
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.7)",
});
}
return config;
});
this.instance.interceptors.response.use(
(res) => {
this.loading?.close();
return res;
},
(err) => {
this.loading?.close();
return err;
}
);
}
request<T = any>(config: RequestConfig): Promise<T> {
if (!config.showLoading) {
this.showLoading = false;
}
return new Promise((resolve, reject) => {
this.instance
.request<any, Data<T>>(config)
.then((res) => {
resolve(res.data);
this.showLoading = true;
})
.catch((err) => {
reject(err);
this.showLoading = true;
});
});
}
get<T = any>(config: RequestConfig): Promise<T> {
return this.request({ ...config, method: "GET" });
}
post<T = any>(config: RequestConfig): Promise<T> {
return this.request({ ...config, method: "POST" });
}
delete<T = any>(config: RequestConfig): Promise<T> {
return this.request({ ...config, method: "DELETE" });
}
patch<T = any>(config: RequestConfig): Promise<T> {
return this.request({ ...config, method: "PATCH" });
}
}
export default AxiosRequest;