Appearance
在项目开发使用组件时候,分全量安装 和 按需引入 自动导入三种方式
全局引入
全局引入(Global Import) 全局引入意味着一旦组件被引入,它就可以在整个 Vue 应用中使用,无需在每个单文件组件(SFC)中单独引入。这种使用方式 一般在在你的主入口文件(通常是 main.js
或 main.ts
)中,以 Element Plus 为例:
js
import ElementPlus from 'element-plus'; // 全部组件导入
import 'element-plus/lib/theme-chalk/index.css'; // 全部样式导入
const app = createApp(App);
app.use(ElementPlus);
如果想让组件有ts 提示可以导入 ElementPlus
的类型声明文件,你需要先使用 Volar,请在 tsconfig.json 中通过 compilerOptions.type 指定全局组件类型:
js
/// <reference types="element-plus/global" />
或者
js
// tsconfig.json
{
"compilerOptions": {
// ...
"types": ["element-plus/global"]
}
}
- 优点: 简单易用,不需要在每个组件中单独引入。
- 缺点: 可能会增加最终的打包体积,因为即使你没有使用某个组件,它也会被包括在内
按需引入
按需引入(On-Demand Import)意味着只有当组件实际被使用时,它才会被引入和打包。我们可以手动在页面引入需要的组件 和 组件样式
html
<template>
<div>
<Button type="primary">Primary Button</Button>
<Button>Default Button</Button>
<Button type="dashed">Dashed Button</Button>
<!-- 其他Button的使用方式 -->
</div>
</template>
<script setup>
import { Button } from 'ant-design-vue'; // 注意修改引入路径
</script>
<style lang="scss">
@import 'ant-design-vue/lib/button/style';
// 添加其他样式导入
</style>
当然也可以在入口文件将这个事解决掉,这样就不用在每个页面都引入了
js
import { createApp } from 'vue';
import App from './App.vue';
import { Button, Input, DatePicker, /* 其他组件 */ } from 'ant-design-vue'; // 导入需要的组件
import 'ant-design-vue/lib/button/style'; // 导入组件的样式
import 'ant-design-vue/lib/input/style'; // 导入Input组件的样式
import 'ant-design-vue/lib/date-picker/style'; // 导入DatePicker组件的样式
/* 导入其他组件的样式 */
import router from './router'; // 如果使用了路由,导入路由实例
const app = createApp(App);
// 注册需要的组件
app.use(Button);
app.use(Input);
app.use(DatePicker);
/* 注册其他组件 */
// 如果使用了路由,挂载路由实例
app.use(router);
app.mount('#app');
也可以将这部分注册的方法进行封装
js
import { App } from 'vue';
import { Button, Input, DatePicker, /* 其他组件 */ } from 'ant-design-vue';
// 封装的批量注册方法
function registerAntDesignComponents(app: App): void {
const components = [
Button,
Input,
DatePicker,
/* 其他组件 */
];
components.forEach(component => {
app.use(component);
});
}
export default registerAntDesignComponents;
在 main.ts 中使用
js
import { createApp } from 'vue';
import App from './App.vue';
import registerAntDesignComponents from './registerAntDesignComponents'; // 导入注册方法
import 'ant-design-vue/lib/button/style'; // 导入组件的样式
import 'ant-design-vue/lib/input/style'; // 导入Input组件的样式
import 'ant-design-vue/lib/date-picker/style'; // 导入DatePicker组件的样式
/* 导入其他组件的样式 */
import router from './router'; // 如果使用了路由,导入路由实例
const app = createApp(App);
// 使用封装的注册方法
registerAntDesignComponents(app);
// 如果使用了路由,挂载路由实例
app.use(router);
app.mount('#app');
也可以自定义组件名导入
js
import { ElButton } from 'element-plus'
app.component(ElButton.name, ElButton)
上面的方法还需要每次都要手动导入css 因此后来诞生了新的方法,通过babel-plugin-import
来解决引入组件还需要引入样式 来进行按需加载,加入这个插件后,可以省去 style 的引入。就可以直接写法如下不用引入css
js
import { Button } from 'ant-design-vue';
但这种仍然需要手动引入组件,而且还必须使用 babel
但在element-plus中,可以使用 unplugin-element-plus
插件来替代 babel-plugin-import
,当使用插件会自动转换,针对不同打包工具使用可以参考 或者可以使用 vite-plugin-style-import:
js
import { ElButton } from 'element-plus'
// ↓ ↓ ↓ ↓ ↓ ↓
import { ElButton } from 'element-plus'
import 'element-plus/es/components/button/style/css'
- 优点: 减少了最终的打包体积,只有实际使用的组件会被包括。
- 缺点: 需要在每个使用组件的文件中单独引入,稍微繁琐。
自动导入(目前主流)
自动导入可以分为两大类自动导入组件和第三方库,组件就是我们常见的vue 第三方组件库,至于 第三方库 这里指的是 第三方手动导入的例如 dayjs 等第三方js 工具库
正是这样的两种分类因此自动导入就有了两种功能的自动导入库,unplugin-vue-components
和 unplugin-auto-import
unplugin-vue-components
unplugin-vue-components
专为 Vue 组件设计,可以自动导入 支持 Vue2 和 Vue3 组件和指令。可以不需要手动引入组件,能够让开发者就像全局组件那样进行开发,但实际上又是按需引入,且不限制打包工具,不需要使用 babel
安装
bash
npm i unplugin-vue-components -D
# or
pnpm add -D unplugin-vue-components
并且提供了内置的解析器用于流行的 UI 库,比如 Vuetify,Ant Design Vue 和 Element Plus,使用 ElementPlus 为例
bash
// 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: [
Components({
resolvers: [ElementPlusResolver()],
}),
],
})
如果你是webpack 打包工具
js
module.exports = {
// The rest of the config here should be left untouched
plugins: [
require('unplugin-vue-components/webpack')({ /* plugin config here */ }) // This imports and registers the plugin in Webpack
]
}
正常况下,该插件会导入自动导入位于 src/components
路径下的组件,但你也可以通过 dirs 选项进行自定义。如果你使用 TypeScript,该插件能提供自动导入组件的类型支持。
js
import Components from 'unplugin-vue-components/vite'
export default defineConfig(
plugins: [
Components({dirs: ["src/example/dir/here","other/example"]})
]
})
也可以自定义解析器,如果组件名称以 "Example" 开头,它会将组件的名称去掉前缀 "Example" 并指定组件的导入来源为 "example-package"。这样,在使用这个插件时,当你在代码中引用 "ExampleButton" 组件时,它会自动导入 "example-package" 中的 "Button" 组件。这可以帮助你更灵活地组织和导入组件,特别是在项目中使用了多个包或模块时
js
Components({
resolvers: [
(componentName) => {
if (componentName.startsWith("Example")) {
return { name: componentName.slice(6), from: "example-package" };
}
},
],
});
如果为了获得正确的 TypeScript 支持,使用 Volar。Volar 是一个用于 Vue 的语言服务器,它允许你在 IDE/文本编辑器中使用更高级的 Vue 开发特性,比如类型检查、语法突显和自动补全。虽然 Vue 还不支持 TypeScript 的这种用法,但 Volar 已经在这种情况下增加了对类型检查和自动补全的支持,文件以包含 dts 属性,该属性设置为 true,如果安装了 TypeScript,还应该自动启用此选项。您需要做的另一件事是将生成的 components.d.ts
(自动导入的组件类型声明文件,这样就可以在ts中使用组件的时候有提示了) 添加到 tsconfig.js include
"include": [ "components.d.ts"]
列表中。Ts 是包含所有类型的文件,如果您不告诉 TypeScript 包含它,它将不会做任何事情
js
{
dts: true // put this in the unplugin-vue-components config
}
综合来看提供的所有api 介绍:
dirs
: 搜索组件的相对路径目录。extensions
: 组件的有效文件扩展名。globs
: 用于匹配文件名以检测为组件的全局模式。deep
: 是否搜索子目录。resolvers
: 自定义组件解析器。dts
: 生成全局声明的components.d.ts
,默认为true
如果 TypeScript 已安装。directoryAsNamespace
: 允许子目录作为组件的命名空间前缀。collapseSamePrefixes
: 折叠相同的前缀(驼峰敏感)以防止命名空间组件名称中的重复。globalNamespaces
: 忽略命名空间前缀的子目录路径。directives
: 自动导入指令,Vue 3 默认为true
,Vue 2 默认为false
。importPathTransform
: 在解析之前转换路径。allowOverrides
: 允许具有相同名称的组件覆盖其他组件。include
: 转换目标的过滤器。exclude
: 排除的路径。version
: 项目的 Vue 版本,如果未指定,将自动检测。types
: 仅提供库中组件的类型(全局注册)。
示例
javascript
Components({
dirs: ['src/components'],
extensions: ['vue'],
deep: true,
resolvers: [],
dts: true,
directoryAsNamespace: false,
collapseSamePrefixes: false,
globalNamespaces: [],
directives: true,
importPathTransform: v => v,
allowOverrides: false,
include: [/\.vue$/, /\.vue\?vue/],
exclude: [/[\\/]node_modules[\\/]/],
version: '3',
types: []
})
- 关于types数组用于注册全局组件的类型。数组中有一个对象,该对象指定了从 example-package 包中导入两个组件(ExampleComponentOne 和 ExampleComponentTwo)的类型这在你使用某些库(如路由库)提供的全局组件时特别有用。
js
{
dts: true,
types: [{
from: 'example-package',
names: ['ExampleComponentOne', 'ExampleComponentTwo'],
}],
}
- 自定义ui简单实现 resolvers
js
Components({
resolvers: [
// ... 其他解析器
// 自定义xx-ui解析器
(name) => {
// name为项目编译时加载到的自定义组件,String类型大驼峰格式的组件名
// 例如:name = XxButton
// 判断组件前缀
if (name.startsWith('Xx')){
return {
// 包名,XxButton -> Button
importName: name.slice(2),
// 路径直接写包名即可,因为我们已经安装了这个包
path: 'xx-ui'
}
}
}
]
})
unplugin-auto-import
unplugin-auto-import
该插件主要用于自动导入 JavaScript 语法和库。它可以自动导入 Vue Composition API、JavaScript 语法、甚至是你自己定义的函数或对象。减少了手动引入的步骤
bash
pnpm add -D unplugin-auto-import
# or
npm i -D unplugin-auto-import
知道这两个库后以element-plus为例,组件可以分为两种,一种就是正常的组件这类组件使用 unplugin-vue-components
就能帮助自动导入,一种事反馈组件,这类组件需要使用 unplugin-auto-import
来帮助自动导入 整体最基本使用如下
js
// 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()], // 解决 import { ElMessage } from 'element-plus' 这类组件的导入
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
})
使用的是ts 版本那么他会 生成文件 auto-imports.d.ts
和 是自动导入api声明文件,这样就可以在ts中使用组件的时候有提示了,需要将这两个文件 配置在 tsconfig.json
中的 include
中,这样就可以在ts中使用组件的时候有提示了 "include": [ "auto-imports.d.ts"]
一些常用的其他属性配置
include
:中指定的文件类型或文件路径才会被 unplugin-auto-import 插件处理,从而进行自动导入,例如.ts
,.tsx
,.js
,.jsx
,.vue
,.md
等。如果只有配置.vue
文件会被 unplugin-auto-import 插件处理,其他类型的文件(如 .js, .ts, .jsx, .tsx 等)将不会进行自动导入imports
: 定义全局导入的模块和别名。支持预设(如'vue'
,'vue-router'
)和自定义设置。defaultExportByFilename
: 是否根据文件名自动导入默认模块。dirs
: 指定目录来自动导入模块。dts
: 生成对应的.d.ts
文件,用于 TypeScript 支持。vueTemplate
: 是否在 Vue 模板内进行自动导入。resolvers
: 自定义解析器,与unplugin-vue-components
兼容。injectAtEnd
: 是否在其他导入语句的末尾注入自动导入。eslintrc
: 生成对应的.eslintrc-auto-import.json
文件,用于 ESLint 配置。
示例配置
javascript
AutoImport({
include: [
/\.[tj]sx?$/, // .ts, .tsx, .js, .jsx
/\.vue$/, /\.vue\?vue/, // .vue
/\.md$/, // .md
],
imports: [
'vue',
'vue-router',
{
'@vueuse/core': [
'useMouse',
['useFetch', 'useMyFetch'],
],
'axios': [
['default', 'axios'],
],
},
],
dts: './auto-imports.d.ts', // dts: path.resolve(pathSrc, 'types', 'components.d.ts') // (false) 配置文件生成位置,默认是根目录 /components.d.ts
vueTemplate: false,
resolvers: [/* ... */],
injectAtEnd: true,
eslintrc: {
enabled: false,
filepath: './.eslintrc-auto-import.json',
globalsPropValue: true,
},
})
为什么配置 eslintrc
字段,当使用 unplugin-auto-import
这个自动导入功能时,有一个小问题:有些代码检查工具(比如ESLint)可能不知道这些自动导入的内容,它们可能会误认为你使用了一些 未定义 的变量或函数,从而给你报错。
为了解决这个问题,unplugin-auto-import
提供了一个 eslintrc 设置。这个设置可以帮助你自动生成一个特殊的配置文件,告诉 ESLint:“嘿,这些自动导入的内容是已经定义好的,不要给我报错哦!”
具体来说,这个 eslintrc 设置有几个选项
enabled
: 这个选项决定是否要生成那个特殊的配置文件。默认是不生成的,但如果你想生成,就把它设置为 true。filepath
: 这是那个特殊配置文件的保存位置。默认是在项目的根目录下,名为 .eslintrc-auto-import.json。globalsPropValue
: 这个选项决定在配置文件中,如何描述那些自动导入的内容。大多数情况下,你不需要改这个设置。
json
eslintrc: {
enabled: true, // 启用这个功能
filepath: './.eslintrc-auto-import.json', // 配置文件路径
globalsPropValue: 'readonly', // 设置全局变量为只读
}
eslintrc
配置完后要在 eslint 配置文件的 extends 中进行声明
json
extends: [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/eslint-config-typescript',
'@vue/eslint-config-prettier/skip-formatting',
'./.eslintrc-auto-import.json',
]
有关 两者使用的注意事项
提供了 unplugin-vue-components 中 resolvers 属性的ui 库 会存在 css icon 等图标库的配置
unplugin-auto-import 和 unplugin-vue-components 的正确使用方式
unplugin-vue-components 源码原理分析