初始化项目
使用vite脚手架模板创建项目,这里我使用pnpm作为包管理工具
arduino
# pnpm
pnpm create vite my-vue-app --template vue
bash
cd my-vue-app
pnpm install
得到基础项目目录
安装eslint进行语法检测
csharp
pnpm add -D eslint
执行eslint初始化命令
csharp
npx eslint --init
根目录新建.eslintignore文件,配置eslint校验范围,这样只会校验src下的ts/js/vue文件
css
**/*.ts
**/*.js
**/*.vue
!src/**/*.ts
!src/**/*.js
!src/**/*.vue
安装prettier规范代码风格
css
pnpm add --save-dev --save-exact prettier eslint-config-prettier eslint-plugin-prettier
由于eslint和prettier规则可能存在冲突,需要安装eslint-config-prettier和eslint-plugin-prettier 在根目录新建.prettierrc.json配置文件,进行prettier规则配置(可按个人喜好进行配置)
json
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"singleQuote": true,
"semi": true,
"trailingComma": "none",
"bracketSpacing": true,
"endOfLine": "auto"
}
同时在eslint配置文件的extends的末尾加入一行
此时我们检测一下前面步骤是否成功,打开App.vue文件,如果看到ts代码后面因为没有分号eslint标红了,说明prettier和eslint的代码风格检查生效了,此时按ctrl+s保存文件,如果自动格式化添加";"了,说明我们都配置成功了
安装husky和lint-stage
husky
包含很多git hook(钩子),常用有:pre-commit、commit-msg、pre-push
。类似于生命周期的概念,可以在我们进行git操作的不同时期执行相应命令。
lint-staged
这个工具一般结合 husky 来使用,它可以让 husky 的 hook 触发的命令只作用于 git add
那些文件(即 git 暂存区的文件),而不会影响到其他文件。
sql
pnpm add --save-dev husky lint-staged
初始化husky
csharp
npx husky init
此时根目录下多了一个.husky文件夹,里面有个pre-commit文件,在里面写入
bash
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged
在package.json中增加lint-staged配置
安装commitlint
校验提交信息格式
bash
npm install @commitlint/cli @commitlint/config-conventional -D
在根目录下新建.commitlintrc.json
文件,定义提交信息格式
perl
{
"extends": [
"@commitlint/config-conventional"
]
}
在.husky文件夹下新建commit-msg文件,添加hook钩子,添加以下代码
bash
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx --no-install commitlint --edit $1
配置别名
配置别名要修改ts配置和vite配置,为防止node的中的变量被ts报错,需要安装node的类型
sql
pnpm add -D @types/node
配置tsconfig.json文件,在compilerOptions下面加入如下代码,然后重启vscode,防止ts配置未生效
修改vite.config.ts文件,添加以下代码
安装路由
csharp
pnpm add vue-router
在src目录下新建router文件夹,新建index.ts
javascript
import { createRouter, createWebHashHistory } from 'vue-router';
import App from '@/App.vue';
// 路由规则
const routes = [
{
path: '/',
component: App,
children: [
{ path: '', redirect: '/home' },
{
path: '/home',
name: 'home',
component: () => import('@/views/Home.vue')
},
{
path: '/login',
name: 'login',
component: () => import('@/views/Login.vue')
},
{
// vue-router@4的变化,舍弃*通配符
path: '/:pathMatch(.*)*',
name: '404',
component: () => import('@/views/404.vue')
}
]
}
];
const router = createRouter({
history: createWebHashHistory(),
routes
});
export default router;
在main.ts中引入
ini
import router from '@/router';
const app = createApp(App);
// 路由
app.use(router);
安装axios
csharp
pnpm add axios
在src目录下新建utils/request.ts文件,封装axios
typescript
import axios, { AxiosError, AxiosRequestConfig } from 'axios';
interface RESPONSE<T = unknown> {
code: number;
msg: string;
data: T;
}
export const instance = axios.create({
timeout: 10 * 1000, // 30s超时
withCredentials: false,
headers: {
'Content-Type': 'application/json'
}
});
instance.interceptors.request.use(
(config) => {
// 请求拦截器
// config.headers.Authorization = XXX;
return config;
},
(error) => {
return Promise.reject(error);
}
);
instance.interceptors.response.use(
($http) => {
// 响应拦截器
const res: RESPONSE = $http.data;
if (res.code === 0) {
return $http;
} else {
console.log('interceptors code', res.code);
// 后端的标志位未通过
return Promise.reject(res.msg);
}
},
(e: AxiosError) => {
// axios请求未成功,例如出现网络错误
return Promise.reject(e.message);
}
);
const request = async <T = unknown>(config: AxiosRequestConfig): Promise<T> => {
const $http = await instance.request<RESPONSE<T>>(config);
const res = $http.data;
return res.data;
};
export default request;
安装pinia
csharp
pnpm add pinia
在src目录下新建store/index.ts,文件,定义store
typescript
// src/store/index.ts
import { defineStore } from 'pinia';
import { createPinia } from 'pinia';
interface GlobalState {
token: string;
userInfo: unknown;
}
// defineStore 调用后返回一个函数,调用该函数获得 Store 实体
export const GlobalStore = defineStore({
id: 'GlobalState', // id: 必须的,在所有 Store 中唯一
// state: 返回对象的函数
state: (): GlobalState => ({
token: '',
userInfo: {}
}),
getters: {},
actions: {
// 不使用箭头函数
setToken(token: string) {
this.token = token;
},
setUserIngo(userInfo: unknown) {
this.userInfo = userInfo;
}
}
});
const pinia = createPinia();
export default pinia;
在main.ts中引入
javascript
import store from '@/store/index';
app.use(store);
安装Less
csharp
pnpm add -D less less-loader
在src目录下新建style目录,在style目录下新建global.less、reset.less、variable.less文件,global定义全局样式,variable定义全局样式变量,reset重置浏览器默认样式,抹平浏览器样式差异。
ruby
// reset.less
// 直接复制https://meyerweb.com/eric/tools/css/reset/
less
// variable.less 根据自身需要定义变量
@color-text: #4e5969;
@color-background: #e5e6eb;
css
// global.less
@import url('./reset.less');
* {
font-weight: 400;
font-size: 14px;
font-family: 'Noto Sans SC';
}
::-webkit-scrollbar {
width: 6px;
height: 6px;
background-color: transparent;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: #b7bdcb;
border-radius: 3px;
box-shadow: 4px 4px 15px rgb(112 124 151 / 5%),
2px 2px 10px rgb(112 124 151 / 10%), 1px 1px 50px rgb(112 124 151 / 15%);
}
::-webkit-scrollbar-thumb:hover {
background-color: rgb(245 238 238 / 100%);
border-radius: 3px;
box-shadow: inset 0 0 6px rgb(0 0 0 / 30%);
}
在vite.config.ts中配置css预处理器,定义变量
dart
export default defineConfig({
// ...
css: {
preprocessorOptions: {
less: {
additionalData: `@import "${resolve(__dirname, 'src/assets/style/variable.less')}";`
}
}
}
});
在main.ts中引入全局样式
arduino
import '@assets/style/global.less';