使用vite创建项目
npm init @vitejs/app [project-name] -- --template
或
yarn yarn create @vitejs/app [project-name] --template
这里我才用yarn 的方式安装,选择vue -> vue-ts,进入项目安装依赖并启动即可。
代码规范(可跳过)
安装Eslint及插件
# eslint 安装
yarn add eslint --dev
# vue插件安装 eslint默认规则的补充
yarn add eslint-plugin-vue --dev
# prettier插件安装 解决prettier和eslint的规则冲突
yarn add eslint-plugin-prettier --dev
# ts插件安装 eslint默认规则的补充
yarn add @typescript-eslint/eslint-plugin --dev
# ts解析器安装 替换默认解析器
# Eslint默认的解析器无法识别部分TS代码
yarn add @typescript-eslint/parser --dev
# 解决ESLint中的样式规范和prettier中样式规范的冲突
# 以prettier的样式规范为准,ESLint 中的样式规范自动失效
yarn add eslint-config-prettier --dev
配置.eslintrc.js
项目的根目录下创建一个 .eslintrc.js,内容如下:
module.exports = {
root: true,
env: {
browser: true,
node: true,
es2021: true,
},
parser: 'vue-eslint-parser',
// 扩展规则
extends: [
'eslint:recommended',
'plugin:vue/vue3-recommended',
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
'prettier',
],
parserOptions: {
ecmaVersion: 12,
parser: '@typescript-eslint/parser',
sourceType: 'module',
ecmaFeatures: {
jsx: true,
},
},
// 注册插件
plugins: ['vue', '@typescript-eslint', 'prettier'],
// 规则 根据自己需要增加
rules: {
'no-var': "error",
'@typescript-eslint/consistent-type-definitions': [
"error",
"interface"
]
}
}
配置 .eslintignore
项目的根目录下创建一个 .eslintignore,内容如下:
# 忽略以下目录的eslint校验
node_modules
dist
安装prettier
yarn add prettier --dev
配置 .prettier.js
项目的根目录下创建一个 .prettierrc.js,内容如下:
// 根据自己需要修改
module.exports = {
tabWidth: 2,
semi: false,
singleQuote: true,
}
配置 .prettierignore
# 忽略以下目录的代码格式化
node_modules
dist
package.json
新增两条脚本,分别做eslint校验和代码格式化
{
"script": {
...
"lint": "eslint src --fix --ext .ts,.tsx,.vue,.js,.jsx",
"prettier": "prettier --write ."
}
}
配置后,跑下命令检验成果,如果规则没生效,尝试重启vscode
#eslint校验
yarn lint
#代码自动格式化
yarn prettier
配置husky
husky 可以为git客户端增加git hooks,比如在这里需要用到的pre-commit
在提交commit的时候,做一个eslint校验和代码格式化的操作
为了避免这个步骤耗时过长,引入lint-staged,一个仅仅过滤出 Git 代码暂存区文件(被 git add 的文件)的工具,仅对暂存区文件做代码校验和格式化
# 通过mrm安装lint-staged,这一步会同时把husky拉下来
# 并在package.json生成初始配置
# 执行之前,确保项目已经git初始化,否则会报.git不存在
yarn add mrm --dev
npx mrm lint-staged
安装完查看
package.json
"scripts": {
...
"prepare": "husky install"
},
"devDependencies": {
...
"husky": ">=6",
"lint-staged": ">=10",
"mrm": "^3.0.10",
},
"lint-staged": {...}
这里我们修改默认配置,以支持自动代码校验和格式化
/* 新增 */
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
/* 修改 */
"lint-staged": {
"*.{ts,tsx,vue,js,jsx}": [
"yarn lint",
"prettier --write",
"git add"
]
}
至此代码规范配置完成,尝试修改不符合规则(爆红)的代码,然后提交,看看代码是否被格式化
配置vite.config.ts
# 安装@types/node引入node声明文件
# 让ts编译器识别node的模块和变量
yarn add @types/node --dev
基础配置
/* eslint-disable camelcase */
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
base: './', // 打包路径
server: { // 开发配置
host: '0.0.0.0',
port: 8080,
open: true,
https: false,
proxy: {},
},
plugins: [vue()], // 插件
})
修改项目目录下的
tsconfig.node.json
/* 该文件被tsconfig.json引用,用于声明node的编译选项 */
{
"compilerOptions": {
/* 新增 allowSyntheticDefaultImports ,使node支持通过import引入commonjs模块 */
"allowSyntheticDefaultImports": true,
"composite": true,
"module": "esnext",
"moduleResolution": "node"
},
"include": ["vite.config.ts"]
}
配置文件引用别名
alias
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { join } from 'path'
const resolve = (path: string) => join(__dirname, path)
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
resolve: {
// 根据需要新增
alias: {
'@': resolve('src'),
},
}
})
修改tsconfig.json
{
"compilerOptions": {
...
/* 使ts编译器识别引用别名 */
"baseUrl": ".",
"paths": {
"@/*":["src/*"]
}
}
}
配置scss预处理器
# 安装sass 和 sass-loader
# vite原生支持sass预处理器,我们只需要安装依赖即可
yarn add sass --dev
yarn add sass-loader --dev
配置全局scss变量 在
src/assets/style下创建index.scss
vite.config.ts中配置
css: {
preprocessorOptions: {
scss: {
additionalData: '@import "@/assets/style/index.scss";',
},
},
},
在项目中直接引用index.scss中声明的变量即可,无需重复引用
vue-router
# 安装vue-router@4
yarn add vue-router@4
根目录下创建
router/index.ts
// Vue Router不再是一个类,而是一组函数
// 具体查看官方文档
import {
createRouter, // 创建路由
createWebHistory, // history模式
RouteRecordRaw // 路由类型
} from 'vue-router'
const routes: RouteRecordRaw[] = [
{
path: '/',
name: 'index',
// vite下,组件路径必须完整,带上vue后缀
component: () => import('@/views/index.vue'),
},
]
const router = createRouter({
history: createWebHistory(),
routes,
})
export default router
// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
createApp(App).use(router).mount('#app')
// App.vue
<template>
<router-view />
</template>
axios请求封装
yarn add axios安装axios
根目录下创建
service目录
封装请求
// service/http/index.ts
// 封装请求
import axios from 'axios'
import { AxiosHttp } from './types'
import initDefaults from './defaults'
import initInterceptors from './interceptors'
initDefaults(axios) // 全局配置
initInterceptors(axios) // 拦截
// 请求函数组
const http: AxiosHttp = {
$get(url, params) {
return axios.get(url, { params }).then((res) => res.data)
},
$post(url, params) {
return axios.post(url, { params }).then((res) => res.data)
},
}
export default http
// service/http/default.ts
// 请求配置
import { Axios } from 'axios'
const initDefaults = (axios: Axios) => {
axios.defaults.baseURL = ''
axios.defaults.timeout = 10000
axios.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8'
}
export default initDefaults
// service/http/interceptors.ts
// 拦截
import { Axios, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios'
const initInterceptors = (axios: Axios) => {
axios.interceptors.request.use(
requestInterceptors,
(err: AxiosError): AxiosError => err
)
axios.interceptors.response.use(
responseInterceptors,
(err: AxiosError): AxiosError => err
)
}
const requestInterceptors = (
config: AxiosRequestConfig<any>
): AxiosRequestConfig<any> => {
console.log('requese interceptors')
// do something...
return config
}
const responseInterceptors = (
response: AxiosResponse<any>
): AxiosResponse<any> => {
console.log('response interceptors')
// do something...
return response
}
export default initInterceptors
// service/http/types.ts
// 类型接口定义
interface HttpResponse<T> {
data: T
message: string
code: number
}
export interface AxiosHttp {
$get<T>(url: string, params?: Object): Promise<HttpResponse<T>>
$post<T>(url: string, params?: Object): Promise<HttpResponse<T>>
}
接口api
// service/api/testApi/index.ts
// 测试接口
import http from '@/service/http'
import { TestApi } from './types'
const testApi: TestApi = {
test: (params) => http.$post('/test', params),
}
export default testApi
// service/http/testApi/types.ts
// 接口参数类型定义
interface TestParams {
keyword: string
}
export interface TestApi {
test: (params: TestParams) => Promise<any>
}
Pinia
yarn add pinia
main.ts中增加
import { createPinia } from 'pinia'
app.use(createPinia())
根目录下创建store目录
// store/age.ts
import { defineStore } from 'pinia'
import { useNameStore } from './name'
export const useAgeStore = defineStore('ageStore', {
state: () => ({ age: 18 }),
getters: {
nextAge: (state) => state.age + 1,
chakAge() {
// 引用其他store的getter
const nameStore = useNameStore()
return nameStore.text + this.nextAge // 通过this引用当前store的其他getter和state
},
},
// 更改状态的方法,支持同步和异步
actions: {
increment() {
this.age++
},
},
})
// store/name
import { defineStore } from 'pinia'
export const useNameStore = defineStore('nameStore', {
state: () => ({ name: 'chak' }),
getters: {
text: (state) => state.name + '的年龄是',
myText() {
return this.text
},
},
})
组件内使用
import { useAgeStore } from '@/store/age'
const ageStore = useAgeStore()
console.log(ageStore.chakAge) // chak的年龄是19
当在getter中声明形参state而不使用时,在函数体通过this只能访问到state而无法访问到其他getter,同时在组件里使用的时候,这个store的所有getter都无法获取,依旧只能获取到state
不知道这是pinia的bug,还是我使用不当导致的。pinia版本是2.0.11,有清楚的小伙伴可以评论区告诉我一下谢谢!!
Element-plus
# 安装element-plus
yarn add element-plus
# 组件自动引入
yarn add unplugin-vue-components unplugin-auto-import --dev
为了减少项目体积,采用按需引入,官方推荐的自动引入的方法,主要用到两个插件,需要在vite中配置
unplugin-vue-componentsOn-demand components auto importing for Vue.组件自动引入
unplugin-auto-importAuto import APIs on-demand for Vite, Webpack, Rollup and esbuild. With TypeScript support. Powered by unplugin.模块自动引入
// element-plus 按需引入配置
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
plugins: [
...
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
VueUse
VueUse is a collection of utility functions based on Composition API.
基于
Composition API的实用函数集合
# 安装
yarn add @vueuse/core
// 组件中使用
import { useMouse } from '@vueuse/core'
const { x, y } = useMouse()
console.log(x.value)
console.log(y.value)
VueUse有丰富的工具函数和用法,本文不做探究
完成
至此大致的框架就已经搭建完毕,根据自己需要再进行增加或删改,之后会搭建后台,基础组件封装等,篇幅有限,另有其他文章介绍,文章有误的地方还请指正,谢谢!!
参考
部分内容参考自 mp.weixin.qq.com/s/3es6ryoTH…