(一)环境准备
- node:16.12.1(node版本需14.0.0以上)
- 项目搭建
- 创建⼀个Vite的初始化项⽬:
npm init vite - 选择模板
- 创建⼀个Vite的初始化项⽬:
(二)项目配置文件修改
1. Vite 配置文件
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': resolve('./src')
}
},
base: './', // 打包路径
server: {
port: 8888, // 服务端口号
open: true, // 服务启动时是否自动打开浏览器
cors: true // 允许跨域
}
})
2. 配置 tsconfig.json文件
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"moduleResolution": "Node",
"strict": true,
"jsx": "preserve",
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["ESNext", "DOM"],
"skipLibCheck": true,
"noEmit": true,
// 👆以上是初始化默认配置
"baseUrl": "./",
// "paths"是相对于"baseUrl"进行解析
// 在vite.config里配置了路径别名resolve.alias,为了让编译 ts 时也能够解析对应的路径,我们还需要配置 paths 选项
"paths": {
"@/*": ["src/*"]
}
/*
在ts中导入js模块会报错找不到类型声明
1.解决方法一:
仅设置 "allowJs": true 即可
注:allowJs设置true时,下方include不可以加入'src/**\/*.js',否则报错'无法写入文件xx因为它会覆盖输入文件'
2.解决方法二:
仅在 env.d.ts 中加入 declare module '*.js'; 模块定义即可
3.总结:和 "include": ["src/**\/*.js"] 没有任何关系
*/
// "allowJs": true, // 允许编译器编译JS,JSX文件
// "typeRoots": [
// "node_modules/@types" // 默认会从'node_modules/@types'路径去引入声明文件
// ],
// "types": ["node"] // 仅引入'node'模块
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }]
}
(三)代码规范配置
1. EditorConfig 配置
(1)作用: 统一不同 IDE 编辑器的代码风格。
(2)配置
- 在项目的根目录下创建
.editorconfig文件:
# Editor configuration, see http://editorconfig.org
# 表示是最顶层的 EditorConfig 配置文件
root = true
[*] # 表示所有文件适用
charset = utf-8 # 设置文件字符集为 utf-8
indent_style = space # 缩进风格(tab | space)
indent_size = 2 # 缩进大小
end_of_line = lf # 控制换行类型(lf | cr | crlf)
trim_trailing_whitespace = true # 去除行首的任意空白字符
insert_final_newline = true # 始终在文件末尾插入一个新行
[*.md] # 表示仅 md 文件适用以下规则
max_line_length = off
trim_trailing_whitespace = false
- VSCode 使用 EditorConfig 需要去插件市场下载插件
EditorConfig VS Code
2. Prettier 配置
(1)作用:当下最流行的代码格式化工具
(2)配置
- 安装Prettier:
npm i prettier -D - 在根目录下创建 .prettierrc 文件
- 配置
.prettierrc关于更多的配置项信息查阅官网{ "useTabs": false, "tabWidth": 2, "printWidth": 100, "singleQuote": true, "trailingComma": "none", "bracketSpacing": true, "semi": false } - 使用:Prettier安装配置好之后,就能使用命令来格式化代码
# 格式化所有文件 (. 表示所有文件) npx prettier --write . - VSCode 编辑器使用 Prettier 配置需要下载插件
Prettier-Code formatter
3. ESlint 配置
(1)作用:查找并报告代码中问题的工具,并且支持部分问题自动修复
(2)配置
- 安装 ESLint:
npm i eslint -D(本地安装) - 配置ESLint
- 执行
npx eslint --init - 选择配置
- 如果自动安装依赖失败,则需要手动安装
npm i @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-config-airbnb-base eslint-plugin-import eslint-plugin-vue -D
- 如果自动安装依赖失败,则需要手动安装
- 操作完成后,会在项目根目录下自动生成
.eslintrc.js配置文件(根据项目实际情况追加ESLint 规则。)
module.exports = { env: { browser: true, es2021: true, node: true }, extends: [ 'plugin:vue/essential', // 'eslint:recommended', // "airbnb-base" 'plugin:vue/vue3-essential', // 添加 prettier 插件,这样,我们在执行 eslint --fix 命令时, // ESLint 就会按照 Prettier 的配置规则来格式化代码,解决prettier/ESLint二者冲突问题。 'plugin:prettier/recommended' // "plugin:@typescript-eslint/recommended" ], overrides: [], // "parser": "@typescript-eslint/parser", parserOptions: { ecmaVersion: 'latest', // 默认的eslint配置无法检测ts的语法,有些关键字会报错,解决interface关键字等识别报错的问题 parser: '@typescript-eslint/parser', sourceType: 'module' }, plugins: ['vue', '@typescript-eslint'], rules: { // 我们主要使用以下规则配置 // 错误急别分为三类 // 1、off 或 0 表示关闭验证规则 // 2、warn 或 1 表示开启警告验证规则 // 3、error 或 2 表示开启错误验证规则,程序会报错退出 semi: [2, 'never'], // 禁止尾部使用分号“ ; ” // "semi": ["warn", "never"], 'no-var': 'error', // 禁止使用 var indent: ['error', 2], // 缩进2格 'no-mixed-spaces-and-tabs': 'error', // 不能空格与tab混用 quotes: [2, 'single'], // 使用单引号 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', // 其它的规则可以去eslint查看,根据自己需要进行添加 // vue template模板元素第一行最多10个属性 'vue/max-attributes-per-line': [ 2, { singleline: 10, //一行最多可以放下10个属性 multiline: { max: 1, allowFirstLine: false } } ], // 关闭名称校验(使用大驼峰命名方式或者用“-”连接单词) 'vue/multi-word-component-names': 'off' // "vue/singleline-html-element-content-newline": "off", // "vue/multiline-html-element-content-newline": "off", // "vue/name-property-casing": ["error", "PascalCase"], // "vue/no-v-html": "off", // 'vue/html-closing-bracket-newline': 'off', // 'vue/singleline-html-element-content-newline': 'off', } } - 执行
- VSCode 使用 ESLint 配置文件需要去插件市场下载插件
ESLint- 如果配置完Eslint提示不生效(可能版本不匹配),就尝试关掉编辑器后重开,或者卸载VSCode的ESLint插件然后重新安装,
- 设置编辑器保存文件时自动执行 eslint --fix 命令进行代码风格修复,VSCode 在 settings.json 设置文件中,增加以下代码:
"editor.codeActionsOnSave": { "source.fixAll.eslint": true } ``
(3)测试
在 main.ts 中写一段不符合eslint规则的代码 ,执行npx eslint src/main.ts检查是否报错提示,报错则配置成功
4. 解决 Prettier 和 ESLint 的冲突
(1)作用
ESLint 和 Prettier 配置规则可能会出现用 Prettier 格式化后的代码,ESLint 检测到格式有问题的,从而抛出错误提示的情况,解决两者冲突问题,需要用到 eslint-plugin-prettier 和 eslint-config-prettier。
eslint-plugin-prettier将 Prettier 的规则设置到 ESLint 的规则中。eslint-config-prettier关闭 ESLint 中与 Prettier 中会发生冲突的规则。 最后形成优先级:Prettier 配置规则 > ESLint 配置规则。
(2)配置
- 安装插件
npm i eslint-plugin-prettier eslint-config-prettier -D
- 在 .eslintrc.js 添加 prettier 插件。
module.exports = {
...
extends: [
...
'plugin:prettier/recommended' // 添加 prettier 插件
],
...
}
这样,我们在执行 eslint --fix 命令时,ESLint 就会按照 Prettier 的配置规则来格式化代码,从而解决二者冲突问题。
5. 插件
(1)Volar
- vue3项目就不要使用Vetur插件了,它不支持很多vue3特性,会有很多红线警告。
- 请使用官方推荐插件
Volar,现已更名为Vue Language Features,再搭配TypeScript Vue Plugin
(四)代码提交检验配置
- Git Husky是一个基于Git的钩子管理工具,它允许开发者在代码提交或推送等Git操作前执行自定义的脚本。
- Husky可以帮助团队在代码提交前进行代码质量检查、测试运行、格式化等操作,以确保代码满足预定义的要求和规范。
- 通过使用Git Husky,开发团队可以轻松地将代码质量检查和预定义的规范集成到Git工作流中。这有助于保持项目的一致性、团队协作和提高代码质量。
husky包含很多 hook(钩子),常用有:pre-commit、commit-msg、pre-push。
1. husky配置:pre-commit
(1)作用:让没通过 ESLint 检测和修复的代码禁止提交
(2)配置
- 安装:运行
npx husky-init,npm install
在项目初始化一个 husky 配置,这行命令做了四件事:- 安装
husky到开发依赖
- 在项目根目录下创建
.husky目录; - 在
.husky目录创建pre-commit hook,并初始化pre-commit命令为npm test
- 修改
package.json的 scripts,增加"prepare": "husky install"
到这里,husky 配置完毕,现在我们来使用它:
- 安装
(3)使用
- 在 package.json 文件的 scripts 中添加命令:
"lint:fix": "eslint --fix --ext .vue,.js,.ts src"或
"lint:fix": "eslint --fix ./src --ext .vue,.js,.ts"
这句话的意思是:- 当我们执行
npm run lint:fix时, - 会先对
src目录下所有的.vue、.js、.ts文件执行eslint --fix命令, - 对
warning等级的代码进行自动修复 (error等级的代码是不能修复的,需要手动解决)
- 当我们执行
- 修改
.husky/pre-commithook 文件的触发命令:npm run lint:fix- 可以先在终端单独运行命令
npm run lint:fix看看,没问题再放到.husky/pre-commit文件中 - 注意:
#!/usr/bin/env sh必须放到第一行,上边不能有其他语句
- 可以先在终端单独运行命令
- 上面这个
pre-commithook 文件的作用是:- 当我们执行
git commit -m "xxx"时,会执行npm run lint:fix命令 - 然后对
src目录下所有的.vue、.js、.ts文件执行eslint --fix命令, - 如果
ESLint通过,成功commit,否则终止commit。
- 当我们执行
(4)测试
- 执行
git commit -m "xxx",看是否会触发husky - pre-commit hook,触发则配置成功
(5)报错解决
解决办法:把.pre-commit文件中的 #!/usr/bin/env sh放到第一行,上边其他信息全部删掉
2. husky + lint-staged 配置
(1)作用
lint-staged这个工具一般结合 husky 来使用,它可以让 husky 的 hook 触发的命令只作用于git add那些文件(即 git 暂存区的文件),而不会影响到其他文件。- husky 配置完还会存在一个问题:有时候我们明明只改动了一两个文件,却要对所有的文件执行
eslint --fix。
假如这是一个历史项目,我们在中途配置了 ESLint 规则,那么在提交代码时,也会对其他未修改的“历史”文件都进行检查,可能会造成大量文件出现 ESLint 错误,显然不是我们想要的结果。 - 通过lint-staged,我们可以做到只用 ESLint 修复此次写的代码,而不去影响其他的代码。
- husky 配置完还会存在一个问题:有时候我们明明只改动了一两个文件,却要对所有的文件执行
(2)配置
- ① 安装 lint-staged:
npm i lint-staged -D; - ② 在
package.json里增加lint-staged配置项;
这行命令表示:只对 git 暂存区的 .vue、.js、.ts 文件执行 eslint --fix"lint-staged": { "*.{vue,js,ts}": "eslint --fix" }, - ③ 修改
.husky/pre-commithook 的触发命令为:npx lint-staged - 至此,husky 和 lint-staged 组合配置完成。
(3)测试
3. husky配置:commit-msg
(1)作用:对commit的信息进行校验
(2)配置
① 方法一
- 执行下面的命令
#!/usr/bin/env sh
# 对commit的文本信息进行校验
# 【方法一】
MSG=`awk '{printf("%s",$0)}' $1`
if [[ $MSG =~ ^(revert: )?(create|feat|fix|conflict|style|save|stash|delete|tool|docs|dx|refactor|revert|perf|test|workflow|build|ci|chore|types|hotfix|update|wip|release)(\(.+\))?(:|:).*$ ]]
then
# echo -e "\033[32m Success: git commit 校验通过! \033[0m"
echo -e ""
else
echo -e "\033[31m Error: 请遵循 type(scope):message 的格式提交 \033[m"
echo -e "\033[31m Error: type 必须为以下类型之一: [feat,fix,docs,style,delete,refactor,test,chore, ...] \033[m"
echo -e "\033[31m 详见 .husky/verifyCommit.js文件 \033[m"
echo -e "\033[31m 例如: feat(模块名称): 文字描述 \033[m"
exit 1
fi
② 方法二(会报错,待解决)
- 在 .husky文件下新建
verifyCommit.ts
//verifyCommit.ts
const msg = require('fs').readFileSync('.git/COMMIT_EDITMSG', 'utf-8').trim()
const commitRE =
/^(revert: )?(feat|fix|docs|dx|style|refactor|perf|test|workflow|build|ci|chore|types|wip|release)(\(.+\))?: .{1,50}/
const mergeRe = /^(Merge pull request|Merge branch)/
console.log('1.git commit开始校验')
if (!commitRE.test(msg)) {
console.log('2.git commit校验中')
if (!mergeRe.test(msg)) {
console.log('3.git commit信息校验不通过')
console.error(`git commit的信息格式不对, 需要使⽤ title(scope): desc的格式`)
process.exit(1)
}
} else {
console.log('4.git commit信息校验通过')
}
- 执行下面的命令
npx husky add .husky/commit-msg "node ./verifyCommit.ts" - 执行后.husky文件夹下会出现新的文件commit-msg
#!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" # 执行./verifyCommit.ts文件中的内容 node .husky/verifyCommit.ts
(3)测试
- 执行
git commit -m "测试commit格式校验",校验不通过 - 执行
git commit -m "test:测试commit格式校验",校验通过:
(五)工具库配置
1. 路由配置
(1)配置
- ① 安装:安装支持vue3的路由:
npm i vue-router@4 - ② 创建:
src/router/index.ts文件
// src/router/index.ts
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
export const routes: Array<RouteRecordRaw> = [
{
path: '/',
name: 'app',
meta: { title: 'app' },
component: () => import('@/App.vue')
},
{
path: '/home',
name: 'Home',
component: () => import(/* webpackChunkName: "Home" */ '@/views/home-page.vue')
},
{
path: '/router',
name: 'Router',
component: () => import('@/views/router-page.vue')
},
// { path: '/:pathMatch(.*)*', redirect: '/' } // 替代vue2中的'*'通配符路径
{ path: '/', redirect: { name: 'Home' } }
]
const router = createRouter({
history: createWebHashHistory(), // history 模式则使用 createWebHistory()
routes
})
export default router
- ③ 挂载:main.ts 文件中挂载
import { createApp } from 'vue'
import App from '@/App.vue'
import router from '@/router/index'
createApp(App).use(router).mount('#app')
(2)测试
在App.vue 文件中测试
<router-link to="/home">路由跳转</router-link>
<router-view></router-view>
3. vuex 配置
(1)配置
- 安装:支持Vue3的状态管理工具
npm i vuex@next - 创建
src/store/index.ts文件
import { createStore } from 'vuex'
const defaultState = {
count: 0
}
// Create a new store instance.
export default createStore({
state() {
return defaultState
},
// mutations:同步修改数据, mutation内部的函数会把state作为参数,
mutations: {
add(state: typeof defaultState) {
// 我们直接操作state.count就可以完成数据的修改。
state.count += 1
}
},
// actions:异步修改数据
actions: {
// increment(context) {
// context.commit('increment')
// }
// 这个配置中所有的函数,可以通过解构获得 commit函数。
// 内部的异步任务完成后,就随时可以调⽤commit来执⾏mutations去更新数据。
asyncAdd({ commit }) {
setTimeout(() => {
commit('add') //可以调⽤commit来执⾏mutations去更新数据。
}, 1000)
}
},
getters: {
double(state: typeof defaultState) {
return 2 * state.count
}
}
})
- 挂载:main.ts 文件中挂载
...
import store from '@/store/index'
createApp(App).use(store).mount('#app')
(2)测试
// src/views/demo/store-demo.vue
<template>
<div>
<h2>计数器(store)</h2>
<p @click="add">同步修改:{{ count }}</p>
<p @click="asyncAdd">异步修改:{{ count }}</p>
<p>计算属性getters:{{ double }}</p>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { useStore } from 'vuex'
let store = useStore()
// 从计算属性中获取vuex
// 使用state获取vuex中的值
let count = computed(() => {
return store.state.count
})
// 使用getters获取vuex中的值
let double = computed(() => {
return store.getters.double
})
let color = ref('pink') //css中使用
// 同步
function add() {
store.commit('add')
color.value = Math.random() > 0.5 ? 'green' : 'pink'
}
// 异步
function asyncAdd() {
store.dispatch('asyncAdd')
}
</script>
<style scoped>
p {
color: v-bind(color);
}
</style>
3. axios 配置
(1)配置
- 安装
Axios: (跟vue版本无关,安装最新即可):npm i axios - 配置
Axios: 根据常规规范,axios封装的方法放在src/utils/http.ts
// src/utils/http.ts
import axios from 'axios'
// import { Message } from 'element-plus'
// 创建axios实例
// 创建请求时可以用的配置选项
const instance = axios.create({
baseURL: '',
withCredentials: true,
timeout: 1000
})
// axios的全局配置
instance.defaults.headers.post = {
'Content-Type': 'application/x-www-form-urlencoded'
}
instance.defaults.headers.common = {
'Auth-Type': 'company-web',
'X-Requested-With': 'XMLHttpRequest',
token: 'sdfjlsdfjlsdjflsjflsfjlskd'
}
// 添加请求拦截器(post只能接受字符串类型数据)
// 对所有的http请求进⾏统⼀拦截,确保在请求发出之前,从本地存储中获取token,
instance.interceptors.request.use(
(config) => {
const token = '' //TODO,获取token,getToken()
if (token && config.headers) {
config.headers['X-Token'] = token
}
return config
},
(error) => {
return Promise.reject(error)
}
)
const errorHandle = (status: any, other: any) => {
// switch (status) {
// case 400:
// // Message.error('信息校验失败')
// break
// case 401:
// Message.error('认证失败')
// break
// case 403:
// Message.error('token校验失败')
// break
// case 404:
// Message.error('请求的资源不存在')
// break
// default:
// Message.error(other)
// break
// }
}
// 添加响应拦截器
// 后端数据如果出错的话,接⼝还要进⾏统⼀拦截,
// ⽐如接⼝返回的错误是登录状态过期,那么就需要提⽰⽤⼾跳转到登录⻚⾯重新登录。
instance.interceptors.response.use(
// 响应包含以下信息data,status,statusText,headers,config
(response) => {
const res = response.data
if (res.code !== 200) {
console.log('接口信息报错', res.message)
return Promise.reject(new Error(res.message || 'Error'))
} else {
return Promise.resolve(res)
}
},
(error) => {
// Message.error(err)
// if (error) {
// errorHandle(response.status, response.data)
return Promise.reject(error)
// }
// Message.error('请求失败')
// return true
}
)
export default instance
(2)使用
import Http from '@/utils/http'
export default defineComponent({
setup() {
// const store = useStore()
const getData = () => {
Http.get('url').then((res: Object) => {
console.log(res)
})
}
return {
store,
getData
}
}
})
4. sass配置
(1)安装
安装:npm i sass -D
卸载:npm uninstall sass-loader
(2)使用
<style lang="scss"></style>
5. 组件库安装-element plus
(1)配置
- 安装组件:
npm install element-plus --save - 安装图标:
npm install @element-plus/icons-vue - 挂载:main.ts 文件中挂载
// main.ts
...
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
// 如果您正在使用CDN引入,请删除下面一行。
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
const app = createApp(App)
app.use(ElementPlus).mount('#app')
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
6. MOCKJS
(1)安装
npm i mockjs vite-plugin-mock -D
(2)配置
- vite.config.ts配置
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
// mock
import { viteMockServe } from 'vite-plugin-mock'
// https://vitejs.dev/config/
export default defineConfig(({ command }) => {
return {
// 插件
plugins: [
vue(),
// mock 数据的 dev环境
viteMockServe({
// supportTs: true, // 是否开启支持ts
mockPath: 'mock',// 设置mockPath为根目录下的mock目录
localEnabled: command === 'serve',// 设置是否监视mockPath对应的文件夹内文件中的更改
logger: true //是否在控制台显示请求日志
})
],
resolve: {
alias: {
'@': resolve(__dirname, 'src')//resolve('./src')
}
},
// 配置公共样式文件
css: {
preprocessorOptions: {
scss: {
additionalData: '@import "./src/styles/index.scss";'
}
}
},
base: './', // 打包路径
server: {
port: 8888, // 服务端口号
open: true, // 服务启动时是否自动打开浏览器
cors: true // 允许跨域
}
}
})
(3)使用
- 根目录下创建
mock/ index.ts
export default [{
url: '/mock/api/getAppInfo',
method: 'get',
response: () => {
return {
code: 0,
title: 'mock请求测试'
}
}
}]
- 使用 axios 请求mock数据
<template>
<div />
</template>
<script setup>
import axios from 'axios'
axios.get('/mock/api/getAppInfo').then((res) => {
console.log(res) // {code: 0, title: 'mock请求测试'}
})
</script>
(六)package.json文件
{
"name": "vue3-cli",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vue-tsc && vite build",
"preview": "vite preview",
"prepare": "husky install",
"lint:fix": "eslint --fix ./src --ext .vue,.js,.ts"
},
"lint-staged": {
"*.{vue,js,ts}": "eslint --fix"
},
"dependencies": {
"@typescript-eslint/eslint-plugin": "^5.43.0",
"@typescript-eslint/parser": "^5.43.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-vue": "^9.7.0",
"vue": "^3.2.41"
},
"devDependencies": {
"@vitejs/plugin-vue": "^3.2.0",
"eslint": "^8.27.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.2.1",
"husky": "^8.0.0",
"lint-staged": "^13.0.3",
"prettier": "^2.7.1",
"typescript": "^4.6.4",
"vite": "^3.2.3",
"vite-plugin-eslint": "^1.8.1",
"vue-tsc": "^1.0.9"
}
}