"*.{js,jsx,vue,ts,tsx}": [
"npm run lint",
// "git add" 之前的版本需要手动把 lint 过程中修改的代码手动 add,新版本不需要了
vite-plugin-eslint
npm install vite-plugin-eslint --save-dev
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import eslintplugin from 'vite-plugin-eslint'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(),eslintplugin({'配置参数'})]
commit 提交规范
Commit message 和 Change log 编写指南
Install commitlint
要让 TypeScript 正确推断 Vue 组件选项中的类型,需要使用 defineComponent 全局方法定义组件:
import { defineComponent } from 'vue'
const Component = defineComponent({
// 已启用类型推断
//如果你使用的是[单文件组件](https://v3.cn.vuejs.org/guide/single-file-component.html),则通常会被写成:
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
// 已启用类型推断
</script>
vue3中ts相关写法
Vue3 中的<script setup>语法
vue3支持三种写法
Option Api
Composition API
<script setup> (Composition API 的语法糖)
defineProps,defineEmits,defineExpose,withDefaults 为全局的 可以不import 直接使用
eslint配置 .eslintrc.js 中配置则不会对此进行引入校验
module.exports = {
globals: {
defineProps: 'readonly',
defineEmits: 'readonly',
defineExpose: 'readonly',
withDefaults: 'readonly'
script-setup用法
该连接为github仓库连接 可能网络问题打不开
script-setup用法 一个中文博客
配置转换JSX和TSX
vite中JSX
npm i @vitejs/plugin-vue-jsx --save-dev
vite.config.ts配置
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
vueJsx({
//配置选项
<template>
</template>
<script setup lang="tsx">
const abc = <h1>abc</h1>
</script>
单独一个组件文件 text.tsx
//函数式组件
export default () => {
return (
<h1>text函数式组件</h1>
//需要有状态的组件 options API
import { defineComponent } from '@vue/runtime-core'
export default defineComponent({
props:{
msg:{
type:String
render(){
return (
<div>{ this.msg }</div>
//需要有状态的组件 组合式 API
import { defineComponent,ref } from '@vue/runtime-core'
interface PropsType {
msg:string
export default defineComponent({
props:{
msg:{
type:String
setup(){
const count = ref (0)
return (props:PropsType ) => (
<p>{props.msg}</p>
<p>{count}</p>
初始化VueRouter
安装vue-router
npm install vue-router@4
// src\router\index.ts
import { createRouter, RouteRecordRaw, createWebHashHistory } from 'vue-router'
const routes: RouteRecordRaw[] = [
path: '/',
component: () => import('../views/home/index.vue')
path: '/login',
component: () => import('../views/login/index.vue')
const router = createRouter({
history: createWebHashHistory(),
routes
export default router
// src\main.ts
import { createApp } from 'vue'
import router from './router'
import App from './App.vue'
createApp(App).use(router).mount('#app')
初始化 Vuex
安装Vuex
npm install vuex@next --save
// src\store\index.ts
import { createStore } from 'vuex'
const store = createStore({
state: {},
getters: {},
mutations: {},
actions: {},
modules: {}
export default store
// src\main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
createApp(App)
.use(router)
.use(store)
.mount('#app')
结合ts优化后
//store/index.ts
import { createStore, useStore as baseUseStore, Store } from 'vuex'
import { InjectionKey } from 'vue'
export interface State {
count: number
// 定义 injection key
export const key: InjectionKey<Store<State>> = Symbol('store')
export const store = createStore<State>({
state: {
count: 0
mutations: {
increment(state) {
state.count++
// 定义自己的 `useStore` 组合式函数 //调用该 useStore 可以推断出state属性及类型
export function useStore() {
return baseUseStore(key)
export default store
// vuex.d.ts
import { ComponentCustomProperties } from 'vue'
import { Store } from 'vuex'
import { State } from './store/index'
declare module '@vue/runtime-core' {
// 声明自己的 store state
// interface State {
// count: number
// 为 `this.$store` 提供类型声明
interface ComponentCustomProperties {
$store: Store<State>
配置模块路径别名
vite不自带@等路径别名
import xxx from '@/views/xxx.vue' //不支持src别名@符 所以要手动配置
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// 注意:在 ts 模块中加载 node 核心模块需要安装 node 的类型补充模块:npm i -D @types/node
import path from 'path'
// https://vitejs.dev/config/
export default defineConfig({
resolve: {
alias: {
'@': path.resolve(__dirname, './src')
// tsconfig.json
//所有以@开头的都指向src
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
// js
import xxx from '@/api/xxx.ts'
// html
<img src="@/assets/logo.png">
// css
@import url("@/styles/index.scss");
background: url("@/assets/logo.png");
CSS样式管理
vite css配置 文档
Vite 也同时提供了对 .scss, .sass, .less, .styl 和 .stylus 文件的内置支持。没有必要为它们安装特定的 Vite 插件,但必须安装相应的预处理器依赖:
# .scss and .sass
npm install -D sass
# .less
npm install -D less
# .styl and .stylus
npm install -D stylus
如果是用的是单文件组件,可以通过 <style lang="sass">(或其他预处理器)自动开启。
注意事项:
● Vite 为 Sass 和 Less 改进了 @import 解析,以保证 Vite 别名也能被使用。
● 另外,url() 中的相对路径引用的,与根文件不同目录中的 Sass/Less 文件会自动变基以保证正确性。
● 由于 Stylus API 限制,@import 别名和 URL 变基不支持 Stylus。
● 你还可以通过在文件扩展名前加上 .module 来结合使用 CSS modules 和预处理器,例如 style.module.scss。
深度作用操作符新语法::deep(<inner-selector>)
样式目录结构
variables.scss # 全局 Sass 变量
mixin.scss # 全局 mixin
common.scss # 全局公共样式
transition.scss # 全局过渡动画样式
index.scss # 组织统一导出
全局样式都写在 src/styles 目录下,每个页面自己对应的样式都写在自己的 .vue 文件之中。
// index.scss
@import './variables.scss';
@import './mixin.scss';
@import './transition.scss';
@import './common.scss';
然后在 main.ts 中导入 index.scss:
//main.ts 这里仅仅是加载了全局样式,并不能实现在组件内直接使用全局变量样式
import "./styles/index.scss"
在单独组件里使用全局变量 需要单独加载
//xxx.vue
<style lang="scss" scoped>
@import '@/styles/variables.scss';
.font{
color:$color;
</style>
要想在全局单文件中不用单独引入就可以使用scss全局变量 需要配置使用全局样式
配置使用全局样式变量
css-preprocessoroptions
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import path from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
vueJsx({
// 配置选项
resolve: {
alias: {
'@': path.join(__dirname, 'src')//绝对路径
css: {
preprocessorOptions: {
// 给 sass-loader 传递选项
sass: {
// @/ 是 src/ 的别名
// 所以这里假设你有 `src/variables.sass` 这个文件
// 注意:在 sass-loader v8 中,这个选项名是 "prependData"
additionalData: `@import "@/styles/variables.scss"`
// 默认情况下 `sass` 选项会同时对 `sass` 和 `scss` 语法同时生效
// 因为 `scss` 语法在内部也是由 sass-loader 处理的
// 但是在配置 `prependData` 选项的时候
// `scss` 语法会要求语句结尾必须有分号,`sass` 则要求必须没有分号
// 在这种情况下,我们可以使用 `scss` 选项,对 `scss` 语法进行单独配置
scss: {
additionalData: `@import "~@/variables.scss";`
// 给 less-loader 传递 Less.js 相关选项
less: {
// http://lesscss.org/usage/#less-options-strict-units `Global Variables`
// `primary` is global variables fields name
globalVars: {
primary: '#fff'
自动注册全局组件
glob-impor
全局组件放在 components 目录下
- components
+ foo
+ index.vue
+ index.ts
+ bar
+ index.vue
+ index.ts
- main.ts
// main.ts
const app = createApp(App)
const modules = import.meta.globEager('./components/**/index.ts')
for (const path in modules) {
app.use(modules[path].default)
// components/foo/index.ts
import { App } from '@vue/runtime-dom'
import Component from './index.vue'
export default {
install (app: App) {
app.component('Foo', Component)
// components/bar/index.ts
import { App } from '@vue/runtime-dom'
import Component from './index.vue'
export default {
install (app: App) {
app.component('Bar', Component)
服务端交互
**基于axios封装请求模块
安装axios
npm i axios
//src/utils/request.ts
import axios from 'axios'
const request = axios.create({
baseURL: '' //基础请求路径
// 请求拦截器
request.interceptors.request.use(
config => {
// 统一设置用户身份 Token
return config
error => {
return Promise.reject(error)
// 响应拦截器
request.interceptors.response.use(
response => {
// 统一处理响应错误,例如 token 无效、服务端异常等
return response
err => {
return Promise.reject(err)
export default request
* 公共基础接口封装
import request from '@/utils/request'
export const getLoginInfo = () => {
return request({
method: 'GET',
url: '/login/info'
* 组件中使用
import { getLoginInfo } from '@/api/common'
import { onMounted } from '@vue/runtime-core'
onMounted(() => {
getLoginInfo().then(res => {
console.log(res)
多环境 baseURL
环境变量和模式
# .env.development
# 开发模式下加载的环境变量
VITE_API_BASEURL=http://a.com
# .env.production
# 生产模式下加载的环境变量
VITE_API_BASEURL=http://b.com
// src\utils\request.ts
const request = axios.create({
// localhost:8080/xxx
// abc.com/xxx
// test.com/xxx
baseURL: import.meta.env.VITE_API_BASEURL
//env.d.ts中对类型声明
/// <reference types="vite/client" />
declare module '*.vue' {
import { DefineComponent } from 'vue'
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
const component: DefineComponent<{}, {}, any>
export default component
interface ImportMetaEnv {
VITE_API_BASEURL: string
// 更多环境变量...
在服务端配置 CORS。
配置开发服务器代理,比如 vite-server.proxy。
在服务端配置 CORS。
配置生产服务器代理,比如 nginx。
CORS 全称为 Cross Origin Resource Sharing(跨域资源共享)。这种方案对于前端来说没有什么工作量,和正常发送请求写法上没有任何区别,工作量基本都在后端(其实也没啥工作量,就是配置一些 HTTP 协议)。
跨源资源共享(CORS)
跨域资源共享 CORS 详解
服务器代理
可能有些后端开发人员觉得配置 CORS 麻烦不想搞,那纯前端也是有解决方案的。
在开发模式下可以下使用开发服务器的 proxy 功能,比如 vite - server.proxy。
但这种方法在生产环境是不能使用的。在生产环境中需要配置生产服务器(比如 nginx、Apache 等)进行反向代理。在本地服务和生产服务配置代理的原理都是一样的,通过搭建一个中转服务器来转发请求规避跨域的问题。
target: 'http://jsonplaceholder.typicode.com',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
// 正则表达式写法
'^/fallback/.*': {
target: 'http://jsonplaceholder.typicode.com',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/fallback/, '')
// 使用 proxy 实例
'/api': {
target: 'http://jsonplaceholder.typicode.com',
changeOrigin: true,
configure: (proxy, options) => {
// proxy 是 'http-proxy' 的实例