vue3.0+TypeScript+Pina+Vite+ElementPlus项目搭建
Vue2.0 马上停止维护了,Vue3.0 是新项目首选项。从零开始搭建一个Vue3全家桶的项目框架,希望对大家有帮助。
参考资料
插件相关文档
- pnpm中文网
- element-plus
- Vite
- NodeJS
- Autoprefixer css、 npmjs网址
- Sass、npmjs网址
- pinia-plugin-persistedstate - Pinia Store 的持久化插件、pinia-plugin-persistedstate 官网
- tailwind css框架
- zipson json数据压缩解压、npmjs网址
- vue router 官网
- ESLint 官网
- Prettier官网
- stylelint官网 、 stylelint中文官网
- editorconfig官网
- cz-git 官网
项目搭建技术相关文档
- Vue3 + Vite + TypeScript + Element-Plus:从零到一构建企业级后台管理系统(前后端开源)
- 【vue3-element-admin】ESLint+Prettier+Stylelint+EditorConfig 约束和统一前端代码规范
- 【vue3-element-admin】Husky + Lint-staged + Commitlint + Commitizen + cz-git 配置 Git 提交规范
- vue3+vite+TypeScript+Element plus+pinia搭建开发脚手架
- 一篇文章教小白学会搭建 vite + ts + vue3 项目,手把手教程,不会算我输(第一篇)
规范文档
功能清单
基础
- [x] 初始化 项目框架
- [x] 整理 环境信息
工程化插件
- [x] 整合 Sass
- [x] 整合 Autoprefixer
- [x] 整合 Pinia
- [x] Pinia 持久化
- [x] 整合 Zipson
- [x] 整合 TailWind Css
- [x] 整合 Element Plus
- [x] 整合 Vue Router
- [ ] 整合 Axios
- [ ] 整合 MockJS
- [x] 配置别名
- [ ] polyfill
- [x] husky
- [x] lint-staged
- [x] commitlint/cli
- [x] Commitizen
- [x] CZ-git
- [ ] browserslist
- [x] 配置 Prettler
- [x] 配置 Eslint
- [x] 配置 Stylellint css检查
- [x] 配置 EditorConfig
- [ ] 配置 tsconfig
- [x] 自动导入
- [ ] 环境变量
- [ ] 跨域处理
- [ ] 动态路由
- [ ] 按钮权限
- [ ] 国际化
- [ ] 暗黑模式
- [x] svg图标库
- [ ] 阿里图标库
- [ ] 打包配置
- [ ] 分包
- [ ] 生成.gz文件
- [ ] js和css文件夹分离
- [ ] 静态资源处理
- [ ] 组件自动化注册
框架赋能
- [ ] 组件封装
- [ ] wangEditor 富文本
- [ ] Echarts 图表
- [ ] 图标选择器
- [ ] 规范配置
- [ ] 代码统一规范
- [ ] git提交统一规范
业务功能
- [ ] 权限控制
- [ ] 按钮权限
- [ ] iframe页面容器
- [ ] 页面弹窗
- [ ] 菜单
- [ ] 面包屑
- [ ] tab标签页
- [ ] 换肤、主题
- [ ] 自动表单
- [ ] 自动表格
- [ ] 登陆页
文档库 vite press
- [ ] 项目搭建
- [ ] 组件文档
基础环境与工具
使用pnpm代替npm
pnpm - 速度快、节省磁盘空间的软件包管理器
npm install -g pnpm
NodeJS
Vite 需要 Node.js 版本 18+,20+。
初始化项目
使用官网命令初始化项目
pnpm create vite
更新依赖
运行项目
项目结构
和vue2没有太大的区别
增加工程化插件
使用sass
其实现在我们的项目已经完全可以运行起来了,但是项目中有一个 style.css 显然不是我们想要的,vite可以原生的支持 scss 文件,我们一般都是使用 scss 写样式。
增加 common.scss 文件,并在 main.ts 中引入
但是此时我们 npm run dev 运行起来的项目提示错误
这是因为 sass 模块是使用 scss 文件必备的工具,所以我们需要安装 sass,注意:
要继续使用 pnpm 命令安装
增加 -D 参数,在开发环境中才使用 sass,因为生产环境,scss 文件会被编译成 css 文件,这个插件是用不到的
pnpm install sass -D
创建 variables.scss
变量文件,添加变量 $bg-color
定义,注意规范变量以 $
开头
// src/styles/variables.scss
$md-bg-color:#242424;
Vite
配置导入 SCSS
全局变量文件
// vite.config.ts
css: {
// CSS 预处理器
preprocessorOptions: {
//define global scss variable
scss: {
javascriptEnabled: true,
additionalData: `@use "@/styles/variables.scss" as *;`
}
}
}
style
标签使用SCSS
全局变量
<!-- src/components/HelloWorld.vue -->
<template>
<div class="box" />
</template>
<style lang="scss" scoped>
.box {
width: 100px;
height: 100px;
background-color: $md-bg-color;
}
</style>
上面导入的 SCSS
全局变量在 TypeScript
不生效的,需要创建一个以 .module.scss
结尾的文件
// src/styles/variables.module.scss
// 导出 variables.scss 文件的变量
:export{
mdBgColor:$md-bg-color
}
TypeScript
使用 SCSS
全局变量
<!-- src/components/HelloWorld.vue -->
<script setup lang="ts">
import variables from "@/styles/variables.module.scss";
console.log(variables.bgColor)
</script>
<template>
<div style="width:100px;height:100px" :style="{ 'background-color': variables.mdBgColor }" />
</template>
现在我们可以安心的使用 scss 了,别忘了把代码提交一下,我们在开发过程中最好尽量保证每个提交都是一个简单的功能。
使用 autoprefixer
autoprefixer 是 postcss 的功能插件,给 web 项目自动增加 css 前缀,兼容各种浏览器。
安装 autoprefixer
pnpm install autoprefixer -D
在配置文件 vite.config.ts 中配置
配置源码
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import autoprefixer from 'autoprefixer';
// https://vitejs.dev/config/
export default defineConfig({
css: {
postcss: {
plugins: [
autoprefixer({// 自动添加前缀 的浏览器
overrideBrowserslist: [
'cover 99.5%',
'Chrome > 31',
'ie >=8',
'last 2 versions', // 所有主流浏览器最近2个版本
],
}),
],
},
},
plugins: [vue()],
});
打包效果
Autoprefixer 未生效时,运行ppm run build 打包出来的代码没有加上自动前缀。
配置生生效后打包出来的效果
使用Pinia
Pinia 是 Vue 的存储库,它允许您跨组件/页面共享状态。 如果您熟悉 Composition API,您可能会认为您已经可以通过一个简单的 export const state = reactive({}). 这对于单页应用程序来说是正确的,但如果它是服务器端呈现的,会使您的应用程序暴露于安全漏洞。 但即使在小型单页应用程序中,您也可以从使用 Pinia 中获得很多好处:
- dev-tools 支持
- 跟踪动作、突变的时间线
- Store 出现在使用它们的组件中
- time travel 和 更容易的调试
- 热模块更换
- 在不重新加载页面的情况下修改您的 Store
- 在开发时保持任何现有状态
- 插件:使用插件扩展 Pinia 功能
- 为 JS 用户提供适当的 TypeScript 支持或 autocompletion
- 服务器端渲染支持
安装pinia
pnpm install pinia
创建入口
在项目的 src/stores 目录下,新建一个 index.ts 文件作为Pinia的入口文件,并创建根Store
import { createPinia } from 'pinia';
const store = createPinia();
export default store;
导入store
在 main.ts 中引入使用即可
import store from './stores'
app.use(store)
在引入store之后,可以在 src/stores 目录下新建一个 modules 文件夹用于定义Sore。这样我们的pinia就可以投入使用了。
创建一个Store
我们在开发中需要根据模块划分状态,这样才方便我们统一管理不同模块下的状态。比如我们开发中会设计到用户模块,因此我们可以在 src/stores/modules
目录下新建一个 user.ts
文件用于用户状态管理,将通过下列代码创建user Store
import { defineStore } from 'pinia';
import { reactive, toRefs } from 'vue';
interface IUserState {
name: string;
}
export const useUserStore = defineStore('user', () => {
// states
const state = reactive<IUserState>({
name: 'old name',
});
// getters
const myName = (): string => `getters ${state.name}`;
// actions
const changeName = (name: string): void => {
state.name = name;
};
return {
...toRefs(state),
myName,
changeName,
};
});
使用Store
应为Store是一个函数,所以在组件中需要调用后才能使用
<script lang="ts" setup>
import { useUserStore } from './stores/modules/user';
const userStore = useUserStore();
</script>
<template>
<div>
{{ userStore.name }} <br>
{{ userStore.myName() }} <br>
<button @click="userStore.changeName('new Name')">changeName</button> <br>
</template>
界面
点击按钮后
Pinia状态持久化
用过vuex的都知道,有时我们会遇到需要将一些状态进行持久化处理,避免刷新浏览器的时候出现数据丢失。当然,你可以选择手动持久化,即手动的将需要持久化存储的数据添加到localStorage或sessionStore中,在定义state的时候默认从这两个Storage中拿。对于小部分数据来说可行,但如果需要大量持久化状态,这种方式就不是很推荐了。要一个个找不说,代码也会大量重复。
因此,我们这时就要借助插件来完成这个操作了。
安装插件
npm i pinia-plugin-persistedstate
导入插件
在 src/stores/index.ts 中引入插件
import { createPinia } from 'pinia';
// 引入持久化插件
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
const store = createPinia();
// 将插件提供给store实例
store.use(piniaPluginPersistedstate)
export default store;
使用 Store :
useUserStore : src/stores/modules/user.ts
import { defineStore } from 'pinia';
import { reactive, toRefs } from 'vue';
interface IUserState {
name: string;
}
export const useUserStore = defineStore('userStore', () => {
// states
const state = reactive<IUserState>({
name: 'old name',
});
// getters
const myName = (): string => `getters ${state.name}`;
// actions
const changeName = (name: string): void => {
state.name = name;
};
return {
...toRefs(state),
myName,
changeName,
};
}, {
// 注意defineStore的第三个参数可以传入插件配置
persist: true,
});
点击按钮修改store里的状态,发现已经被默认存储在了localStorage中。
配置部分数据持久化
那么现在又出现了一个问题:并不是所有的状态都需要持久化呀,只持久化部分数据该怎么办呢?现在就需要对插件进行一个配置了。
在 src/utils 目录下新建 persist.ts 文件,修改存储配置:
import type { PersistedStateOptions } from 'pinia-plugin-persistedstate';
/**
* @description pinia持久化参数配置
* @param {String} key 存储到持久化的 name
* @param {Array} paths 需要持久化的 state name
* @return persist
* */
const piniaPersistConfig = (key: string, paths?: string[]) => {
const persist: PersistedStateOptions = {
key,
storage: window.localStorage,
// storage: window.sessionStorage,
paths,
};
return persist;
};
export default piniaPersistConfig;
观察代码可知,我们不仅可以存储部分状态,并且可以选择存储方式~
因此修改store中的持久化配置:
import { defineStore } from 'pinia';
import { reactive, toRefs } from 'vue';
import piniaPersistConfig from '../../utils/persist';
interface IUserState {
name: string;
lastName: string;
}
export const useUserStore = defineStore('userStore', () => {
// states
const state = reactive<IUserState>({
name: 'old name',
lastName: 'last name',
});
// getters
const myName = (): string => `getters ${state.name}`;
// actions
const changeName = (name: string): void => {
state.name = name;
};
return {
...toRefs(state),
myName,
changeName,
};
}, {
// 注意defineStore的第三个参数可以传入插件配置
// persist: true,
persist: piniaPersistConfig('userStore', ['lastName']),
});
从图片中我们可以看到,只有'lastName'被持久化缓存了下来。
Pinia全局配置前缀
可以全局添加前缀,在 src/stores/index.ts
import { createPinia } from 'pinia';
// 引入持久化插件
import { createPersistedState } from 'pinia-plugin-persistedstate';
const pinia = createPinia();
// 将插件提供给store实例
pinia.use(createPersistedState({
key: id => `__md_persisted__${id}`,
}));
export default pinia;
Zipson 压缩数据
每个浏览器对localStorage 是有限制大小的,你不压缩,有时候你触发了某个bug,你都不知道怎么回事。
安装插件
pnpm install --save zipson
导入插件
import { parse, stringify } from 'zipson';
配置 persist
src/utils/persist.ts
import type { PersistedStateOptions,StorageLike } from 'pinia-plugin-persistedstate';
import { parse, stringify } from 'zipson';
/**
* @description pinia持久化参数配置
* @param {String} key 存储到持久化的 name
* @param {Array} paths 需要化的 state name持久
* @param storage 存储的位置 locationStorage sessionStorage
* @return persist
* */
const piniaPersistConfig = (key: string, paths: string[], storage: StorageLike = localStorage) => {
const persist: PersistedStateOptions = {
key,
paths,
storage,
serializer: {
deserialize: parse,
serialize: stringify,
}
};
return persist;
};
export default piniaPersistConfig;
安装 Tailwind CSS
Tailwind CSS 的工作原理是扫描所有 HTML 文件、JavaScript 组件和任何其他类名称模板,生成相应的样式,然后将它们写入静态 CSS 文件。
它快速、灵活且可靠 — 具有零运行时间。
安装插件
通过 npm 安装 tailwindcss
及其对等依赖项,并创建你的 tailwind.config.js
文件。
pnpm install -D tailwindcss postcss autoprefixer
将 Tailwind 添加到你的 PostCSS 配置中
npx tailwindcss init -p
运行上面指令生成 postcss.config.js 、tailwindcss.config.js 文件
配置 postcss.config.js
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
配置 tailwindcss.config.js
/** @type {import('tailwindcss').Config} */
export default {
content: ["index.html","./src/**/*.{vue,html,js,jsx,ts,tsx}"],
theme: {
extend: {},
},
plugins: [],
}
配置 tailwind.css
src/assets/style/tailwind.css
@tailwind base;
@tailwind components;
@tailwind utilities
导入css
src/main.ts
使用 tailwind
code
<script lang="ts" setup>
</script>
<template>
<div class="flex p-6 font-mono">
<div
class="flex-none w-48 mb-10 relative z-10 before:absolute before:top-1 before:left-1 before:w-full before:h-full before:bg-teal-400">
<img alt="" class="absolute z-10 inset-0 w-full h-full object-cover rounded-lg" loading="lazy"
src="./assets/vue.svg" />
</div>
<form class="flex-auto pl-6">
<div
class="relative flex flex-wrap items-baseline pb-6 before:bg-black before:absolute before:-top-6 before:bottom-0 before:-left-60 before:-right-6">
<h1 class="relative w-full flex-none mb-2 text-2xl font-semibold text-white">
Retro Shoe
</h1>
<div class="relative text-lg text-white">
$89.00
</div>
<div class="relative uppercase text-teal-400 ml-3">
In stock
</div>
</div>
<div class="flex items-baseline my-6">
<div class="space-x-3 flex text-sm font-medium">
<label>
<input checked class="sr-only peer" name="size" type="radio" value="xs" />
<div
class="relative w-10 h-10 flex items-center justify-center text-black peer-checked:bg-black peer-checked:text-white before:absolute before:z-[-1] before:top-0.5 before:left-0.5 before:w-full before:h-full peer-checked:before:bg-teal-400">
XS
</div>
</label>
<label>
<input class="sr-only peer" name="size" type="radio" value="s" />
<div
class="relative w-10 h-10 flex items-center justify-center text-black peer-checked:bg-black peer-checked:text-white before:absolute before:z-[-1] before:top-0.5 before:left-0.5 before:w-full before:h-full peer-checked:before:bg-teal-400">
S
</div>
</label>
<label>
<input class="sr-only peer" name="size" type="radio" value="m" />
<div
class="relative w-10 h-10 flex items-center justify-center text-black peer-checked:bg-black peer-checked:text-white before:absolute before:z-[-1] before:top-0.5 before:left-0.5 before:w-full before:h-full peer-checked:before:bg-teal-400">
M
</div>
</label>
<label>
<input class="sr-only peer" name="size" type="radio" value="l" />
<div
class="relative w-10 h-10 flex items-center justify-center text-black peer-checked:bg-black peer-checked:text-white before:absolute before:z-[-1] before:top-0.5 before:left-0.5 before:w-full before:h-full peer-checked:before:bg-teal-400">
L
</div>
</label>
<label>
<input class="sr-only peer" name="size" type="radio" value="xl" />
<div
class="relative w-10 h-10 flex items-center justify-center text-black peer-checked:bg-black peer-checked:text-white before:absolute before:z-[-1] before:top-0.5 before:left-0.5 before:w-full before:h-full peer-checked:before:bg-teal-400">
XL
</div>
</label>
</div>
</div>
<div class="flex space-x-2 mb-4 text-sm font-medium">
<div class="flex space-x-4">
<button class="px-6 h-12 uppercase font-semibold tracking-wider border-2 border-black bg-teal-400 text-black"
type="submit">
Buy now
</button>
<button class="px-6 h-12 uppercase font-semibold tracking-wider border border-slate-200 text-slate-900"
type="button">
Add to bag
</button>
</div>
<button aria-label="Like" class="flex-none flex items-center justify-center w-12 h-12 text-black" type="button">
<svg aria-hidden="true" fill="currentColor" height="20" width="20">
<path clip-rule="evenodd"
d="M3.172 5.172a4 4 0 015.656 0L10 6.343l1.172-1.171a4 4 0 115.656 5.656L10 17.657l-6.828-6.829a4 4 0 010-5.656z"
fill-rule="evenodd" />
</svg>
</button>
</div>
<p class="text-xs leading-6 text-slate-500">
Free shipping on all continental US orders.
</p>
</form>
</div>
</template>
运行成功了 看到上面界面。
异常情况:
Tailwind Css不生效
按照上述步骤操作后没有见到效果
下面我解决这个问题
找到vite.config.js,我们配置的css模块和文件postcss里内容冲突,我们将这里css配置删掉。修改postcss.config.js
postcss.config.js
export default {
plugins: {
tailwindcss: {},
autoprefixer: {
overrideBrowserslist: [
'cover 99.5%',
'Chrome > 31',
'ie >=8',
'last 2 versions', // 所有主流浏览器最近2个版本
],
},
},
};
然后重新运行项目就能看到效果了
配置IDEA中自动提示
如果 idea 不提示 tailwindcss 的标签,那么可以尝试将安装postcss的版本降低到
pnpm install @tailwindcss/postcss7-compat@2.1.4 --save # "@tailwindcss/postcss7-compat": "2.1.4",
pnpm install tailwindcss@latest # "tailwindcss": "^3.3.7",
此外,插件市场记得安装下面的三个插件,这样提示效果会更加全面:
配置VSCode中自动提示
参考资料:分享4个不可或缺的 VSCode 插件,让 Tailwind CSS开发更简单
- Tailwind CSS IntelliSense
- Tailwind Fold
- Tailwind Documentation
- Tailwind Config Viewer
使用 Element Plus
- 参考资料:
安装插件
pnpm install element-plus # "element-plus": "^2.4.4",
导入组件库
建议使用按需导入
方案一:完整引入
如果你对打包后的文件大小不是很在乎,那么使用完整导入会更方便。 src/main.ts
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'
const app = createApp(App)
app.use(ElementPlus)
app.mount('#app')
方案二:按需导入
您需要使用额外的插件来导入要使用的组件。官方推荐用这种方式
首先你需要安装unplugin-vue-components 和 unplugin-auto-import这两款插件
pnpm install -D unplugin-vue-components unplugin-auto-import # "unplugin-vue-components": "^0.26.0","unplugin-auto-import": "^0.17.2",
然后把下列代码插入到你的 Vite 的配置文件中
vite.config.ts
import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
// ...
plugins: [
// ...
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
})
使用组件
src/App.vue
![image-20231219210037636](./images/vue3.0+TypeScript+Pina+Vite+ElementPlus项目搭建/image-20231219210037636.png
使用 Vue Router
参考资料
安装插件
pnpm install vue-router@4 # "vue-router": "4",
创建页面
在 src 路径下新建 pages 文件夹
新建 account.vue
src/pages/account.vue
<template>
<div @click="toLogin">toLogin</div>
<router-view></router-view>
</template>
<script lang="ts" setup>
import { useRoute, useRouter } from 'vue-router';
const router = useRouter();
function toLogin() {
router.push({
name: 'login',
});
}
</script>
<style scoped>
</style>
新建login.vue
src/pages/login.vue
<template>
<div @click="toAccount">toAccount</div>
<router-view></router-view>
</template>
<script lang="ts" setup>
import { useRoute, useRouter } from 'vue-router';
const router = useRouter();
function toAccount() {
router.push({
name: 'account',
});
}
</script>
新建router配置
在 src 路径下新建 router/index.ts
src/router/index.ts
/**
* @FileName index.ts.ts
* @Author Mad Dragon <395548460@qq.com>
* @Version V 0.0.1
* @Date 2023/12/25 22:12
* @Title
* @Desc
**/
import { createRouter, createWebHistory } from 'vue-router';
export const routes = [
{
path: '/',
redirect: '/login',
},
{
name: 'login',
path: '/login',
component: () => import('../pages/login.vue'),
},
{
name: 'account',
path: '/account',
component: () => import('../pages/account.vue'),
},
];
const router = createRouter({
scrollBehavior: () => ({left: 0, top: 0}),
history: createWebHistory(),
routes,
});
router.beforeEach((to, from, next) => {
next();
});
export default router;
引用router
在main.ts
src/main.ts
import { createApp } from 'vue';
import './assets/style/tailwind.scss';
import './style.css';
import './assets/style/test.scss';
import App from './App.vue';
import store from './stores';
import router from './router';
const app = createApp(App);
app.use(store);
app.use(router);
app.mount('#app');
设置router view
删掉之前没啥用的代码
src/App.vue
<script lang="ts" setup>
</script>
<template>
<router-view></router-view>
</template>
<style lang="scss">
</style>
结果
点击可以切换路由
路径别名配置
相对路径别名配置,使用 @ 代替 src
安装 @types/node
pnpm i @types/node -D # "@types/node": "^20.10.5",
TypeScirpt 编译器配置
tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": [
"ES2020",
"DOM",
"DOM.Iterable"
],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "preserve",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
// 解析非相对模块的基地址,默认是当前目录
"baseUrl": "./",
"paths": {
// 映射路径 相对于 baseUrl
"@/*": [
"src/*",
],
"@a/*": [
"src/assets/*",
],
"@css/*": [
"src/assets/style/*",
],
"@r/*": [
"src/router/*",
],
"@p/*": [
"src/pages/*",
],
"@s/*": [
"src/stores/*",
],
"@u/*": [
"src/utils/*",
],
"@@/*": [
"src/components/*",
],
}
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue"
],
"references": [
{
"path": "./tsconfig.node.json"
}
]
}
Vite 配置
在 vite.config.ts 中设置
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import AutoImport from 'unplugin-auto-import/vite';
import Components from 'unplugin-vue-components/vite';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
import { resolve } from 'path';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
resolve: {
// alias: {
// '@': resolve(__dirname, 'src'),
// },
alias: [
{
find: '@',
replacement: resolve(__dirname, 'src'),
},
{
find: '@a',
replacement: resolve(__dirname, 'src/assets'),
},
{
find: '@css',
replacement: resolve(__dirname, 'src/assets/style'),
},
{
find: '@r',
replacement: resolve(__dirname, 'src/router'),
},
{
find: '@p',
replacement: resolve(__dirname, 'src/pages'),
},
{
find: '@s',
replacement: resolve(__dirname, 'src/stores'),
},
{
find: '@u',
replacement: resolve(__dirname, 'src/utils'),
},
{
find: '@@',
replacement: resolve(__dirname, 'src/components'),
},
],
},
});
路径别名使用
src/main.ts
import { createApp } from 'vue';
// import './assets/style/tailwind.scss';
// import './style.css';
// import './assets/style/test.scss';
// import App from './App.vue';
// import store from './stores';
// import router from './router';
import '@css/tailwind.scss';
import '@css/test.scss';
import '@/style.css';
import App from '@/App.vue';
import store from '@/stores';
import router from '@/router';
const app = createApp(App);
app.use(store);
app.use(router);
app.mount('#app');
src/App.vue
<script lang="ts" setup>
// import HelloWorld from './components/HelloWorld.vue';
import HelloWorld from '@@/HelloWorld.vue';
</script>
<template>
<router-view></router-view>
<HelloWorld></HelloWorld>
</template>
<style lang="scss">
</style>
代码规范
ESLint+Prettier+Stylelint+EditorConfig 约束和统一前端代码规范 ESLint 检测 JS/TS 代码、Prettier 格式化代码、Stylelint 检测 CSS/SCSS 代码和配置 EditorConfig 来全方位约束和统一前端代码规范。
ESLint 代码检测
ESLint 可组装的JavaScript和JSX检查工具,目标是保证代码的一致性和避免错误。
安装 ESLint 插件
VSCode 插件市场搜索 ESLint 插件并安装
安装ESlint依赖
pnpm install -D eslint # "eslint": "^8.56.0",
ESLint 配置
执行命令完成 ESLint 配置初始化
npx eslint --init
根目录自动生成的 .eslintrc.cjs 配置内容如下:
module.exports = {
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:vue/vue3-essential"
],
"overrides": [
{
"env": {
"node": true
},
"files": [
".eslintrc.{js,cjs}"
],
"parserOptions": {
"sourceType": "script"
}
}
],
"parserOptions": {
"ecmaVersion": "latest",
"parser": "@typescript-eslint/parser",
"sourceType": "module"
},
"plugins": [
"@typescript-eslint",
"vue"
],
"rules": {
}
}
ESLint 解析器配置
在默认配置基础上需要修改解析器为 vue-eslint-parser ,不然在检测执行中出现 error Parsing error: '>' expected
的解析错误,修改 .eslintrc.cjs 如下:
Package.json 新增依赖
{
"devDependencies": {
"eslint": "^8.56.0", // EsLint的核心代码
"eslint-plugin-vue": "^9.19.2" // 为Vue使用Eslint的插件
"@typescript-eslint/parser": "^6.18.0", // ESLint的解析器,用于解析typescript,从而检查和规范Typescript代码
"@typescript-eslint/eslint-plugin": "^6.18.0", // 这是一个ESLint插件,包含了各类定义好的检测Typescript代码的规项目下新建 .eslintrc.cjs,配置 eslint 校验规则
}
}
配置 eslint 校验规则
- 参考资料:ESLint 官网
.eslintrc.cjs
module.exports = {
env: {
browser: true,
es2021: true,
},
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:vue/vue3-essential',
],
overrides: [
{
env: {
node: true,
},
files: ['.eslintrc.{js,cjs}'],
parserOptions: {
sourceType: 'script',
},
},
{
files: ['*.vue'],
rules: {
// 这里写覆盖vue文件的规则
'no-unused-vars': [0],
},
},
],
parser: 'vue-eslint-parser',
parserOptions: {
ecmaVersion: 'latest',
parser: '@typescript-eslint/parser',
sourceType: 'module',
},
plugins: ['@typescript-eslint', 'vue'],
rules: {
// JavaScript/ESLint 推荐的规则
'no-console': 'warn', // 不允许使用 console.log 等
'no-unused-vars': 'warn', // 不允许存在未使用的变量
'no-undef': 'error', // 不允许使用未定义的变量
'no-debugger': 'warn', // 不允许使用debugger
// 禁止使用alert
'no-alert': 'warn',
// 禁用var,用let和const代替
'no-var': 'warn',
// 允许每个作用域有多个变量声明,但需要将连续的变量声明组合成一个声明
'one-var': ['error', 'consecutive'],
// 要求使用 === 和 !==
eqeqeq: 'error',
// 强制使用骆驼拼写法命名约定
camelcase: 'warn',
// 强制使用一致的缩进
indent: ['error', 4],
// 强制结尾分号
semi: ['warn', 'always'],
// 强制字符串单引号
quotes: ['error', 'single'],
// 当最后一个元素或属性与结束 ] 或 } 在不同的行时需要尾随逗号,当最后一个元素或属性与结束 ] 或 } 在同一行时不允许尾随逗号
'comma-dangle': ['error', 'always-multiline'],
// Vue/ESLint 推荐的规则
// HTML 缩进为 2 个空格
'vue/html-indent': ['error', 4],
// 属性名使用连字符形式
'vue/attribute-hyphenation': 'error',
// 关闭自闭合标签要求,根据个人或团队喜好配置
'vue/html-self-closing': 'warn',
'vue/max-attributes-per-line': [
'error',
{
// 单行最多 6 个属性
singleline: 6,
// 每行最多一个属性
multiline: {
max: 1,
},
},
],
// 不允许使用 v-html 指令
'vue/no-v-html': 'error',
// 不允许存在未使用的组件
'vue/no-unused-components': 'error',
// TypeScript/ESLint 推荐的规则
// 不允许存在未使用的 TypeScript 变量
'@typescript-eslint/no-unused-vars': 'error',
// 不允许不显式指定导出函数的返回类型
'@typescript-eslint/explicit-module-boundary-types': 'warn',
// 不允许使用 any 类型
'@typescript-eslint/no-explicit-any': 'warn',
// 组件命名规范校验
'vue/multi-word-component-names': 'off',
},
};
ESLint 忽略配置(.eslintignore)
根目录新建 .eslintignore 文件,添加忽略文件, ESLint 校验会忽略这些文件,配置如下:
dist
node_modules
public
.husky
.vscode
.idea
*.sh
*.md
src/assets
.eslintrc.cjs
.prettierrc.cjs
.stylelintrc.cjs
ESLint 检测指令
package.json 添加 eslint 检测指令:
"scripts": {
"lint:eslint": "eslint \"src/**/*.{vue,js,jsx,ts}\" --fix"
},
执行命令进行ESLint检测:
pnpm run lint:eslint
ESLint 保存自动检测
vscode
打开 File → Preferences → Settings 搜索 Editor: Code Actions On Save 选择 Workspace标签设置工作区,点击 Edit in settings.json
{
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true // 开启eslint检测
}
}
webStorm
Prettier 代码格式化
Prettier一个“有态度”的代码格式化工具
安装 Prettier 依赖
pnpm install -D prettier eslint-config-prettier eslint-plugin-prettier
- prettier:prettier插件的核心代码
- eslint-config-prettier:解决ESLint中的样式规范和prettier中样式规范的冲突,以prettier的样式规范为准,使ESLint中的样式规范自动失效
- Aslant-plugin-prettier:将prettier作为ESLint规范来使用
安装 Prettier 插件
VSCode
VSCode 插件市场搜索 Prettier - Code formatter
插件安装
webStorm
配置 Prettier 规则
项目根目录下新建 .prettierrc.cjs,配置 prettier 规则
/**
* @FileName .prettierrc.cjs
* @Author Mad Dragon <395548460@qq.com>
* @Version V 0.0.1
* @Date 2024/1/17 14:56
* @Title Prettierrc
* @Desc
* Prettier 官网 https://www.prettier.cn/docs/options.html
**/
module.exports = {
// (x)=>{},单个参数箭头函数是否显示小括号。(always:始终显示;avoid:省略括号。默认:always)
arrowParens: 'avoid',
// 开始标签的右尖括号是否跟随在最后一行属性末尾,默认false
bracketSameLine: false,
// 对象字面量的括号之间打印空格 (true - Example: { foo: bar } ; false - Example: {foo:bar})
bracketSpacing: false,
// 是否格式化一些文件中被嵌入的代码片段的风格(auto|off;默认auto)
embeddedLanguageFormatting: 'auto',
// 指定 HTML 文件的空格敏感度 (css|strict|ignore;默认css)
htmlWhitespaceSensitivity: 'css',
// 当文件已经被 Prettier 格式化之后,是否会在文件顶部插入一个特殊的 @format 标记,默认false
insertPragma: false,
// 在 JSX 中使用单引号替代双引号,默认false
jsxSingleQuote: false,
// 每行最多字符数量,超出换行(默认80)
printWidth: 120,
// 超出打印宽度 (always | never | preserve )
proseWrap: 'preserve',
// 对象属性是否使用引号(as-needed | consistent | preserve;默认as-needed:对象的属性需要加引号才添加;)
quoteProps: 'as-needed',
// 是否只格式化在文件顶部包含特定注释(@prettier| @format)的文件,默认false
requirePragma: false,
// 结尾添加分号
semi: true,
// 使用单引号 (true:单引号;false:双引号)
singleQuote: true,
// 缩进空格数,默认2个空格
tabWidth: 4,
// 元素末尾是否加逗号,默认es5: ES5中的 objects, arrays 等会添加逗号,TypeScript 中的 type 后不加逗号
trailingComma: 'es5',
// 指定缩进方式,空格或tab,默认false,即使用空格
useTabs: false,
// vue 文件中是否缩进 <style> 和 <script> 标签,默认 false
vueIndentScriptAndStyle: false,
// 在变为默认行为之前,请尝试使用漂亮的新三元格式。
experimentalTernaries: false,
// 在HTML、Vue和JSX中每行强制执行一个属性。
singleAttributePerLine: true,
};
配置 Prettier 忽略配置(.prettierignore)
dist
node_modules
public
.husky
.vscode
.idea
*.sh
*.md
src/assets
Prettier 格式化指令
package.json 添加 prettier 格式化指令:
"scripts": {
"lint:prettier": "prettier --write \"**/*.{js,ts,json,css,less,scss,vue,html,md}\""
}
Prettier 格式化&验证
pnpm run lint:prettier
Prettier 保存自动格式化
VSCode
VSCode 的 settings.json
配置:
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
}
WebStorm
Stylelint CSS 检测
Stylelint 一个强大的 CSS linter(检查器),可帮助您避免错误并强制执行约定。官方网站: https://stylelint.io
注意官网明确指出 Stylelint 作为 CSS 代码规范检测而不作为代码格式化工具使用(Prettier 是更好的选择),新版本(15.0.0)为此废弃相关的 rules
安装 Stylelint 依赖
pnpm install -D stylelint stylelint-config-standard stylelint-config-recommended-scss stylelint-config-recommended-vue postcss postcss-html postcss-scss stylelint-config-recess-order stylelint-config-html
依赖 | 说明 | 备注 |
---|---|---|
stylelint | Stylelint 核心库 | stylelint官网 stylelint中文官网 |
stylelint-config-standard | Stylelint 标准共享配置 | stylelint-config-standard 文档 |
stylelint-config-recommended-scss | 扩展 stylelint-config-recommended 共享配置并为 SCSS 配置其规则 | stylelint-config-recommended-scss 文档 |
stylelint-config-recommended-vue | 扩展 stylelint-config-recommended 共享配置并为 Vue 配置其规则 | stylelint-config-recommended-vue 文档 |
stylelint-config-recess-order | 提供优化样式顺序的配置 | CSS 书写顺序规范 |
stylelint-config-html | 共享 HTML (类似 HTML) 配置,捆绑 postcss-html 并对其进行配置 | stylelint-config-html 文档 |
postcss-html | 解析 HTML (类似 HTML) 的 PostCSS 语法 | postcss-html 文档 |
postcss-html | PostCSS 的 SCSS 解析器 | postcss-scss 文档,支持 CSS 行类注释 |
安装 Stylelint 插件
VScode
VScode 插件搜索 Stylelint
并安装
WebStorm
Stylelint 配置
根目录下新建 .stylelintrc.cjs
文件
module.exports = {
// 继承推荐规范配置
extends: [
'stylelint-config-standard',
'stylelint-config-recommended-scss',
'stylelint-config-recommended-vue/scss',
'stylelint-config-html/vue',
'stylelint-config-recess-order',
],
// 指定不同文件对应的解析器
overrides: [
{
files: ['**/*.{vue,html}'],
customSyntax: 'postcss-html',
},
{
files: ['**/*.{css,scss}'],
customSyntax: 'postcss-scss',
},
],
// 定义自定义规则
rules: {
// 允许 global, export, v-deep等伪类
'selector-pseudo-class-no-unknown': [
true,
{
ignorePseudoClasses: ['global', 'export', 'v-deep', 'deep'],
},
],
'order/properties-alphabetical-order': true,
'block-no-empty': true,
'scss/at-rule-no-unknown': [
true,
{
ignoreAtRules: ['tailwind'],
},
],
'property-no-unknown': [
true,
{
ignoreProperties: ['/^md/'],
},
],
},
};
Stylelint 忽略配置(.stylelintignore)
dist
node_modules
public
.husky
.vscode
.idea
*.sh
*.md
src/assets
Style lint 检测指令
Package.json 添加Stylelint 检测指令
"scripts": {
"lint:stylelint": "stylelint \"**/*.{css,scss,vue,html}\" --fix"
}
Stylelint 检测&验证
执行一下命令
pnpm run lint:stylelint
Stylelnit 保存自动检测
Vscode的 settings.json
配置
{
"editor.codeActionsOnSave": {
// 开启 Stylelint 保存自动检测
"source.fixAll.stylelint": "always"
},
// Stylelint 校验文件
"stylelint.validate": ["css", "scss", "vue", "html"]
}
EditorConfig 编辑器配置
EditorConfig 主要用于统一不同 IDE 编辑器的编码风格。官方网站: https://editorconfig.org/
配置 EditorConfig
根目录创建 .editorconfig 文件,添加配置如下:
# http://editorconfig.org
root = true
# 表示所有文件适用
[*]
charset = utf-8 # 设置文件字符集为 utf-8
end_of_line = lf # 控制换行类型(lf | cr | crlf)
indent_style = space # 缩进风格(tab | space)
indent_size = 4 # 缩进大小 4
insert_final_newline = true # 始终在文件末尾插入一个新行
trim_trailing_whitespace = true # 删除行尾空格 = 是
# 表示仅 md 文件适用以下规则
[*.md]
max_line_length = off # 关闭最大行长度限制
trim_trailing_whitespace = false # 关闭末尾空格修剪
安装 EditorConfig 插件
VSCode 搜索 EditorConfig for VS Code
插件并安装
配置 Git 提交规范
使用 Husky + Lint-staged + Commitlint —— commitizen + cz-git 来配置 Git提交代码规范。
核心内容是配置 Husky 的 pre-commit
和 commit-msg
两个钩子:
- pre-commit : Husky + Lint-staged 整合实现 Git 提交前代码规范检测/格式化(前提: ESLint + prettier + Stylelint 代码统一规范配置好)
- commit-msg : Husky + Commit + Commitizen + cz-git 整合实现生成规范化且高度自定义的 Git commit message。
使用 Husky
Husky是Git钩子工具,可以设置在git各个阶段(pre-commit、commit-msg等)触发。
官方网站:https://typicode.github.io/husky
安装 Husky 依赖
npx husky-init && pnpm install
自动生成.husky
目录和指令:
使用 Lint-staged
lint-staged 是一个在 git add 到 暂存区的文件运行 linters(ESLint / Prettier / Stylelint)的工具,避免在git commit提交的时候在整个项目执行。
官方网站:https://github.com/okonet/lint-staged
安装 Lint-staged 依赖
pnpm install -D lint-staged
配置 Lint-staged
package.json 中添加不同文件在git提交执行的lint检测配置
"lint-staged": {
"*.{js,ts}": [
"eslint --fix",
"prettier --write"
],
"*.{cjs,json}": [
"prettier --write"
],
"*.{vue,html}": [
"eslint --fix",
"prettier --write",
"stylelint --fix"
],
"*.{scss,css}": [
"stylelint --fix",
"prettier --write"
],
"*.md": [
"prettier --write"
]
}
Lint-staged 指令
"scripts": {
"lint:lint-staged": "lint-staged",
}
修改提交前钩子命令
根目录 .husky
目录下 pre-commit
文件中 npm test
修改 npm run lint:lint-staged
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm run lint:lint-staged
Git 提交代码检测
1、git add 需要提交的文件
2、运行指令
git commit -m "test husky lint-staged"
使用 Commitlint
Commitlint检查您的提交消息是否符合 Conventional commit format。
安装 Commitlint 依赖
pnpm install -D @commitlint/cli @commitlint/config-conventonal
配置 Commitlint
根目录创建 commitlint.config.cjs
配置文件
module.exports = {
// 继承的规则
extends: ['@commitlint/config-conventional'],
// @see: https://commitlint.js.org/#/reference-rules
rules: {
'subject-case': [0], // subject大小写不做校验
// 类型枚举,git提交type必须是以下类型
'type-enum': [
2,
'always',
[
'feat', // 新增功能
'fix', // 修复缺陷
'docs', // 文档变更
'style', // 代码格式(不影响功能,例如空格、分号等格式修正)
'refactor', // 代码重构(不包括 bug 修复、功能新增)
'perf', // 性能优化
'test', // 添加疏漏测试或已有测试改动
'build', // 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)
'ci', // 修改 CI 配置、脚本
'revert', // 回滚 commit
'chore', // 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)
],
],
},
};
添加提交信息校验钩子
执行下面命令生成 commint-msg
钩子用于git提交信息校验
npx husky add .husky/commit-msg "npx --no -- commitlint --edit \$1"
生成配置如下:
Commitlint 验证
正确的提交格式:<type>(<scope>):<subject>
,type 和 subject 默认必填
Commitizen & cz-git
- Commitizen: 基于Node.js 的
git commit
命令行工具,辅助生成标准化规范化的commmit message。 - cz-git: 一款工程性更强,轻量级,高度自定义,标准输出格式的 commitizen适配器。
安装 Commitizen 、cz-git 依赖
pnpm install -D commitizen cz-git
配置 cz-git
修改 package.json
指定使用的适配器
"config": {
"commitizen": {
"path": "node_modules/cz-git"
}
}
cz-git 与 commitlint 进行联动给予加盐信息, 所以便携于 commitlint
配置文件之中 commitlint.config.cjs
module.exports = {
rules: {
...
},
prompt: {
// 自定义命令行提问信息
messages: {
type: '选择你要提交的类型 :',
scope: '选择一个提交范围(可选):',
customScope: '请输入自定义的提交范围 :',
subject: '填写简短精炼的变更描述 :\n',
body: '填写更加详细的变更描述(可选)。使用 "|" 换行 :\n',
breaking: '列举非兼容性重大的变更(可选)。使用 "|" 换行 :\n',
footerPrefixesSelect: '选择关联issue前缀(可选):',
customFooterPrefix: '输入自定义issue前缀 :',
footer: '列举关联issue (可选) 例如: #31, #I3244 :\n',
generatingByAI: '正在通过 AI 生成你的提交简短描述...',
generatedSelectByAI: '选择一个 AI 生成的简短描述:',
confirmCommit: '是否提交或修改commit ?',
},
// prettier-ignore
// 自定义选择类型提示
types: [
{value: 'feat', name: '特性: ✨ 新增功能', emoji: ':sparkles:'},
{value: 'fix', name: '修复: 🐛 修复缺陷', emoji: ':bug:'},
{value: 'docs', name: '文档: 📝 文档变更', emoji: ':memo:'},
{value: 'style', name: '格式: 💄 代码格式(不影响功能,例如空格、分号等格式修正)', emoji: ':lipstick:'},
{value: 'refactor', name: '重构: ♻️ 代码重构(不包括 bug 修复、功能新增)', emoji: ':recycle:'},
{value: 'perf', name: '性能: ⚡️ 性能优化', emoji: ':zap:'},
{value: 'test', name: '测试: ✅ 添加疏漏测试或已有测试改动', emoji: ':white_check_mark:'},
{value: 'build', name: '构建: 📦️ 构建流程、外部依赖变更(如升级 npm 包、修改 vite 配置等)', emoji: ':package:'},
{value: 'ci', name: '集成: 🎡 修改 CI 配置、脚本', emoji: ':ferris_wheel:'},
{value: 'revert', name: '回退: ⏪️ 回滚 commit', emoji: ':rewind:'},
{value: 'chore', name: '其他: 🔨 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)', emoji: ':hammer:'},
],
// 是否开启 commit message 带有 Emoji 字符。
useEmoji: true,
// 设置 Emoji 字符 的 位于头部位置
emojiAlign: 'center',
useAI: false,
aiNumber: 1,
// 设置终端交互部件的主题色
themeColorCode: '',
// 选择一个提交范围配置
scopes: ['框架搭建', '开发规范', '需求整理', '工具类封装', '项目重构'],
allowCustomScopes: true,
allowEmptyScopes: true,
// 设置 选择范围 中 为空选项(empty) 和 自定义选项(custom) 的 位置
customScopesAlign: 'top',
// 自定义 选择范围 中 自定义选项(custom) 在命令行中显示的 名称
customScopesAlias: '自定义',
// 自定义 选择范围 中 为空选项(empty) 在命令行中显示的 名称
emptyScopesAlias: '跳过',
upperCaseSubject: false,
markBreakingChangeMode: false,
allowBreakingChanges: ['feat', 'fix'],
breaklineNumber: 100,
breaklineChar: '|',
skipQuestions: [],
issuePrefixes: [{value: 'closed', name: 'closed: ISSUES has been processed'}],
// 设置 选择 issue 前缀 中 跳过选项(skip) 和 自定义选项(custom) 的 位置
customIssuePrefixAlign: 'top',
// 自定义 选择 issue 前缀 中 跳过选项(skip) 在命令行中显示的 名称
emptyIssuePrefixAlias: '跳过',
// 自定义 选择 issue 前缀 中 自定义选项(custom) 在命令行中显示的 名称
customIssuePrefixAlias: '自定义',
allowCustomIssuePrefix: true,
allowEmptyIssuePrefix: true,
confirmColorize: true,
maxHeaderLength: Infinity,
maxSubjectLength: Infinity,
minSubjectLength: 0,
scopeOverrides: undefined,
defaultBody: '',
defaultIssues: '',
defaultScope: '',
defaultSubject: '',
},
};
添加提交指令
package.json
添加 commit
指令
"scripts": {
"commit": "git-cz"
}
cz-git 验证
执行 commit 指令进行代码提交流程,执行前需将改动的文件通过 git add
添加到暂存区 , 根据提示一步步完善 commit msg 信息。commit 之后 git push 推送到远程仓库可以看到提交信息。
pnpm run commit
编辑器插件
VSCode
安装插件 Commit Message Editor
填写信息,并save,然后提交
查看提交记录
WebStorm
安装插件 git commit template
填写信息
提交
查看提交记录
安装自动导入
Element Plus 官方文档中推荐
按需自动导入
的方式,而此需要使用额外的插件unplugin-auto-import
和unplugin-vue-components
来导入要使用的组件。所以在整合Element Plus
之前先了解下自动导入
的概念和作用
概念
为了避免在多个页面重复引入API
或组件
,由此而产生的自动导入插件来节省重复代码和提高开发效率。
插件 | 概念 | 自动导入对象 |
---|---|---|
unplugin-auto-import | 按需自动导入API | re、reactive、watch、computed等API |
unplugin-vue-components | 按需自动导入组件 | Element Plus 等三方库和指定目录下的自定义组件 |
看下自动导入插件未使用和使用的区别:
unplugin-auto-import
未使用自动导入
使用自动导入
unplugin-vue-components
未使用自动导入
使用自动导入
安装依赖
pnpm install -D unplugin-auto-import unplugin-vue-components
vite.config.ts - 自动导入配置
新建 /src/types
目录用于存放自动导入函数和组件的TS类型声明文件
import {defineConfig} from 'vite';
import vue from '@vitejs/plugin-vue';
import AutoImport from 'unplugin-auto-import/vite';
import Components from 'unplugin-vue-components/vite';
import {ElementPlusResolver} from 'unplugin-vue-components/resolvers';
import {resolve} from 'path';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
AutoImport({
// 自动导入 Vue 相关函数,如:ref, reactive, toRef 等
// 自动导入 pinia 相关函数,如:createPinia, defineStore, mapState 等
// 自动导入 vue-router 相关函数,如:useLink, useRoute, useRouter 等
imports: ['vue', 'pinia', 'vue-router'],
eslintrc: {
// 是否自动生成 eslint 规则,建议生成之后设置 false
enabled: true,
// 指定自动导入函数 eslint 规则的文件
filepath: './.eslintrc-auto-import.json',
},
// 指定自动导入函数TS类型声明文件路径
dts: resolve(__dirname, 'src/types', 'auto-imports.d.ts'),
// 自动导入 elementPlus 相关
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
dts: resolve(__dirname, 'src/types', 'components.d.ts'),
}),
],
});
.eslintrc.cjs - 自动导入函数 eslint规则引入
"extends": [
"./.eslintrc-auto-import.json"
],
tsconfig.json - 自动导入TS类型声明文件引入
{
"include": ["src/**/*.d.ts"]
}
自动导入效果
运行项目 pnpm dev
安装自动导入 element plus Icon
安装 Icon 依赖
pnpm install -D unplugin-icons
vite.config.ts 配置
import {defineConfig} from 'vite';
import vue from '@vitejs/plugin-vue';
import AutoImport from 'unplugin-auto-import/vite';
import Components from 'unplugin-vue-components/vite';
import Icons from 'unplugin-icons/vite';
import IconsResolver from 'unplugin-icons/resolver';
import {ElementPlusResolver} from 'unplugin-vue-components/resolvers';
import {resolve} from 'path';
// eslint-disable-next-line no-undef
const dirname = __dirname;
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
AutoImport({
// 指定自动导入函数TS类型声明文件路径
dts: resolve(dirname, 'src/types', 'auto-imports.d.ts'),
// 是否在 vue 模版中自动导入
vueTemplate: true,
// 自动导入 elementPlus 相关
resolvers: [
// 自动导入 Element Plus 相关函数,如:ElMessage, ElMessageBox... (带样式)
ElementPlusResolver(),
// 自动导入图标组件
IconsResolver({}),
],
}),
Components({
resolvers: [
// 自动导入 Element Plus 组件
ElementPlusResolver(),
IconsResolver({
// element-plus图标库,其他图标库 https://icon-sets.iconify.design/
enabledCollections: ['ep'],
}),
],
dts: resolve(dirname, 'src/types', 'components.d.ts'),
}),
Icons({
// 自动安装图标库
autoInstall: true,
}),
],
});
示例代码
<el-button type="success"><i-ep-SuccessFilled />Success</el-button>
<el-button type="info"><i-ep-InfoFilled />Info</el-button>
<el-button type="warning"><i-ep-WarningFilled />Warning</el-button>
<el-button type="danger"><i-ep-WarnTriangleFilled />Danger</el-button>
效果预览
整合 SVG 图标
通过
vite-plugin-sbg-icons
插件整合Iconfont
第三方图标库实现本地图标
安装依赖
pnpm install -D fast-glob vite-plugin-svg-icons
创建目录
创建 src/assets/icons
目录,放入葱Iconfont赋值的svg
图标
引入脚本
main.js 引入注册脚本
import 'virtual:svg-icons-register';
vite.config.ts 配置插件
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
export default ({command, mode}: ConfigEnv): UserConfig => {
return (
{
plugins: [
createSvgIconsPlugin({
// 指定需要缓存的图标文件夹
// eslint-disable-next-line no-undef
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
// 指定symbolId格式
symbolId: 'icon-[dir]-[name]',
})
]
}
)
}
SVG组件封装
创建 src/components/MdSvgIcon/index.vue
<script lang="ts" setup>
const props = defineProps({
prefix: {
type: String,
default: 'icon',
},
iconClass: {
type: String,
required: false,
},
color: {
type: String,
},
size: {
type: String,
default: 'iem',
},
}),
symbolId = computed(() => `#${props.prefix}-${props.iconClass}`);
</script>
<template>
<svg
:style="`width:${size};height:${size}`"
aria-hidden="true"
class="svg-icon"
>
<use
:fill="color"
:xlink:href="symbolId"
/>
</svg>
</template>
<style scoped>
.svg-icon {
display: inline-block;
width: 1em;
height: 1em;
overflow: hidden;
vertical-align: -0.15em; /* 因icon大小被设置为和字体大小一致,而span等标签的下边缘会和字体的基线对齐,故需设置一个往下的偏移比例,来纠正视觉上的未对齐效果 */
outline: none;
fill: currentcolor; /* 定义元素的颜色,currentColor是一个变量,这个变量的值就表示当前元素的color值,如果当前元素未设置color值,则从父元素继承 */
}
</style>
组件使用
<template>
<el-button type="primary"><md-svg-icon icon-class="snowflake" />SVG 本地图标</el-button>
</template>