尤大推荐的神器unplugin-vue-components,解放双手!以后再也不用呆呆的手动引入(组件,ui(Element-ui)库,vue hooks等)

先看效果 一个import都没有!

本文将介绍下面几个vite插件(可自由搭配,推荐node版本14+) [demo仓库地址] ( github.com/qc-z/vue-te… )

  • 自定义组件自动引入 unplugin-vue-components
  • element-plus 组件自动引入 unplugin-vue-components
  • vue3等插件 hooks 自动引入 unplugin-auto-import/vite
  • message, notification 等引入样式自动引入 vite-plugin-style-import
  • eslint插件 vue-global-api (2022/03/01已不推荐,推荐使用unplugin-auto-import的eslintrc选项)
  • 1 unplugin-vue-components

    1.1 自动导入ui库,该插件内置了大多数流行库解析器

    这里拿几个流行ui库做栗子 Element Plus Ant Design Vue Element UI Headless UI

    npm install unplugin-vue-components -D
    

    然后将下面的代码添加到 Vite 或 webpack 的配置文件。

    Vite配置

    // vite.config.js
    import { defineConfig } from 'vite'
    import Components from 'unplugin-vue-components/vite'
    import {
      ElementPlusResolver,
      AntDesignVueResolver,
      VantResolver,
      HeadlessUiResolver,
      ElementUiResolver
    } from 'unplugin-vue-components/resolvers'
    export default defineConfig({
      plugins: [
        Components({
          // ui库解析器,也可以自定义
          resolvers: [
            ElementPlusResolver(),
            AntDesignVueResolver(),
            VantResolver(),
            HeadlessUiResolver(),
            ElementUiResolver()
    

    Webpack配置

    // webpack.config.js
    const components = require('unplugin-vue-components/webpack')
    const { ElementPlusResolver,AntDesignVueResolver,VantResolver,HeadlessUiResolver,ElementUiResolver } = require('unplugin-vue-components/resolvers')
    module.exports =
      plugins: [
        Components({
          resolvers: [
             AntDesignVueResolver(),
             ElementPlusResolver(),
             VantResolver(),
             HeadlessUiResolver(),
             ElementUiResolver()
    

    插件会生成一个ui库组件以及指令路径components.d.ts文件,详情看这个vue3的issue types(defineComponent): support for expose component types

    // components.d.ts
    // generated by unplugin-vue-components
    // We suggest you to commit this file into source control
    // Read more: https://github.com/vuejs/vue-next/pull/3399
    declare module 'vue' {
      export interface GlobalComponents {
        ElAside: typeof import('element-plus/es')['ElAside']
        ElButton: typeof import('element-plus/es')['ElButton']
        ElContainer: typeof import('element-plus/es')['ElContainer']
        ElDropdown: typeof import('element-plus/es')['ElDropdown']
        ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
        ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
        ElHeader: typeof import('element-plus/es')['ElHeader']
        ElIcon: typeof import('element-plus/es')['ElIcon']
        ElMain: typeof import('element-plus/es')['ElMain']
        ElMenu: typeof import('element-plus/es')['ElMenu']
        ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
        ElResult: typeof import('element-plus/es')['ElResult']
    export { }
    

    想了解其他的打包工具(RollupVue CLI),请参考 unplugin-vue-components

    1.2 自动导入自己的组件

    直接写组件名即可,插件会帮你引入进来 注意别重名

    // vite.config.js
    import { defineConfig } from 'vite'
    import Components from 'unplugin-vue-components/vite'
    export default defineConfig({
      plugins: [
        Components({
          // 指定组件位置,默认是src/components
          dirs: ['src/components'],
          // ui库解析器
          // resolvers: [ElementPlusResolver()],
          extensions: ['vue'],
          // 配置文件生成位置
          dts: 'src/components.d.ts'
    

    插件会生成一个自己组件路径的components.d.ts文件,详情看这个vue3的issue types(defineComponent): support for expose component types

    // components.d.ts
    // generated by unplugin-vue-components
    // We suggest you to commit this file into source control
    // Read more: https://github.com/vuejs/vue-next/pull/3399
    declare module 'vue' {
      export interface GlobalComponents {
        BaseFilter: typeof import('./components/Common/BaseFilter.vue')['default']
        BaseHeader: typeof import('./components/Common/BaseHeader.vue')['default']
        BasePagination: typeof import('./components/Common/BasePagination.vue')['default']
        BaseSidebar: typeof import('./components/Common/BaseSidebar.vue')['default']
        BaseTags: typeof import('./components/Common/BaseTags.vue')['default']
        BaseTitle: typeof import('./components/Common/BaseTitle.vue')['default']
    export { }
    
    // 插件的所有默认配置
    Components({
      // relative paths to the directory to search for components.
      // 要搜索组件的目录的相对路径
      dirs: ['src/components'],
      // valid file extensions for components.
      // 组件的有效文件扩展名。
      extensions: ['vue'],
      // search for subdirectories
      // 搜索子目录
      deep: true,
      // resolvers for custom components
      // 自定义组件的解析器
      resolvers: [],
      // generate `components.d.ts` global declarations, 
      // also accepts a path for custom filename
      // 生成 `components.d.ts` 全局声明,
      // 也接受自定义文件名的路径
      dts: false,
      // Allow subdirectories as namespace prefix for components.
      // 允许子目录作为组件的命名空间前缀。
      directoryAsNamespace: false,
      // 忽略命名空间前缀的子目录路径
      // 当`directoryAsNamespace: true` 时有效
      // Subdirectory paths for ignoring namespace prefixes
      // works when `directoryAsNamespace: true`
      globalNamespaces: [],
      // auto import for directives
      // default: `true` for Vue 3, `false` for Vue 2
      // Babel is needed to do the transformation for Vue 2, it's disabled by default for performance concerns.
      // To install Babel, run: `npm install -D @babel/parser @babel/traverse`
      // 自动导入指令
      // 默认值:Vue 3 的`true`,Vue 2 的`false`
      // 需要 Babel 来为 Vue 2 进行转换,出于性能考虑,它默认处于禁用状态。
      directives: true,
      // filters for transforming targets
      include: [/.vue$/, /.vue?vue/],
      exclude: [/[\/]node_modules[\/]/, /[\/].git[\/]/, /[\/].nuxt[\/]/],
    

    2 unplugin-auto-import/vite

    自动导入vue3的hooks,借助unplugin-auto-import/vite这个插件

    支持vue, vue-router, vue-i18n, @vueuse/head, @vueuse/core等自动引入

    先看效果图

    // 引入前
    import { ref, computed } from 'vue'
    const count = ref(0)
    const doubled = computed(() => count.value * 2)
    //引入后
    const count = ref(0)
    const doubled = computed(() => count.value * 2)
    // 引入前
    import { useState } from 'react'
    export function Counter() {
      const [count, setCount] = useState(0)
      return <div>{ count }</div>
    //引入后
    export function Counter() {
      const [count, setCount] = useState(0)
      return <div>{ count }</div>
    
    npm i -D unplugin-auto-import
    

    Vite配置

    // vite.config.js
    import { defineConfig } from 'vite'
    import AutoImport from 'unplugin-auto-import/vite'
    export default defineConfig({
      plugins: [
        AutoImport({
          imports: ['vue', 'vue-router', 'vue-i18n', '@vueuse/head', '@vueuse/core'],
          // 可以选择auto-import.d.ts生成的位置,使用ts建议设置为'src/auto-import.d.ts'
          // dts: 'src/auto-import.d.ts'
    

    原理: 安装的时候会自动生成auto-imports.d文件(默认是在根目录)

    // Generated by 'unplugin-auto-import'
    // We suggest you to commit this file into source control
    declare global {
      const ref: typeof import('vue')['ref']
      const reactive: typeof import('vue')['reactive']
      const computed: typeof import('vue')['computed']
      const createApp: typeof import('vue')['createApp']
      const watch: typeof import('vue')['watch']
      const customRef: typeof import('vue')['customRef']
      const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
    export {}
    

    可以选择auto-import.d.ts生成的位置,使用ts建议设置为src/auto-import.d.ts

    其他插件 vue-router, vue-i18n, @vueuse/head, @vueuse/core等自动引入的自动引入请查看文档

    // 插件的所有默认配置
    AutoImport({
      // targets to transform
      include: [
        /\.[tj]sx?$/, // .ts, .tsx, .js, .jsx
        /\.vue$/, /\.vue\?vue/, // .vue
        /\.md$/, // .md  
      // global imports to register
      imports: [
        // presets
        'vue',
        'vue-router',
        // custom
          '@vueuse/core': [
            // named imports
            'useMouse', // import { useMouse } from '@vueuse/core',
            // alias
            ['useFetch', 'useMyFetch'] // import { useFetch as useMyFetch } from '@vueuse/core',
          'axios': [
            // default imports
            ['default', 'axios'] // import { default as axios } from 'axios',
          '[package-name]': [
            '[import-names]',
            // alias
            ['[from]', '[alias]']
      // custom resolvers
      // 可以在这自定义自己的东西,比如接口api的引入,工具函数等等
      // see https://github.com/antfu/unplugin-auto-import/pull/23/
      resolvers: [
        /* ... */
    

    3vue-global-api 解决eslint报错(2022/03/01已不推荐,推荐使用unplugin-auto-import的eslintrc选项)

    在页面没有引入的情况下,使用unplugin-auto-import/vite来自动引入hooks,在项目中肯定会报错的,这时候需要在eslintrc.js中的extends引入vue-global-api,这个插件是vue3hooks的,其他自己找找,找不到的话可以手动配置一下globals

    安装 vue-global-api

    npm install vue-global-api -D
    
    // .eslintrc.js
    module.exports = {
      extends: [
        'vue-global-api'
    

    它还为细粒度控制提供了相同的集合和单个 API 选项。

    // .eslintrc.js
    module.exports = {
      extends: [
        // collections
        'vue-global-api/reactivity',
        'vue-global-api/lifecycle',
        'vue-global-api/component',
        // single apis
        'vue-global-api/ref',
        'vue-global-api/toRef',
    

    4 vite-plugin-style-import

    当你使用unplugin-vue-components来引入ui库的时候

    message, notification 等引入样式不生效 安装vite-plugin-style-import即可

    这里以一些流行库为例

    // vite.config.js
    import { defineConfig } from 'vite'
    import styleImport, {
      AndDesignVueResolve,
      VantResolve,
      ElementPlusResolve,
      NutuiResolve,
      AntdResolve
    } from 'vite-plugin-style-import'
    export default defineConfig({
      plugins: [
        styleImport({
          resolves: [
            AndDesignVueResolve(),
            VantResolve(),
            ElementPlusResolve(),
            NutuiResolve(),
            AntdResolve()
          // 自定义规则
          libs: [
              libraryName: 'ant-design-vue',
              esModule: true,
              resolveStyle: (name) => {
                return `ant-design-vue/es/${name}/style/index`
      // 引用使用less的库要配置一下
      css: {
        preprocessorOptions: {
          less: {
            javascriptEnabled: true
    

    5 注意点

    1. element-plus默认是英文

    方案: 在app.vue加上ElConfigProvider

    <template>
      <div id="app">
        <el-config-provider :locale="locale">
          <router-view></router-view>
        </el-config-provider>
      </div>
    </template>
    <script setup>
    import zhCn from 'element-plus/lib/locale/lang/zh-cn'
    const locale = zhCn
    </script>
    

    日期相关组件设置中文:

    <script setup>
    // 日历等与dayjs相关的组件,不想显示中文可以不加
    // 第一种方法 使用中国时区weekStart默认为1
    import 'dayjs/locale/zh-cn'
    // 第二种方法 使用 weekStart可配置(只能是0或者1)
    import dayjs from 'dayjs'
    // 引入英文即为英文
    import cn from 'dayjs/locale/zh-cn'
    dayjs.locale({
      ...cn,
      weekStart: 1
    const locale = zhCn
    </script>
    

    2. 按需加载不支持指令方式导入,需要手动导入(仅作记录)

    这个是我在作者下面提的issue (2021/11/02记录现在已支持指令)

    方案: 新建文件 element-plus-directive.js

    import { ElLoading, ElMessage } from 'element-plus'
     * 按需导入 Element Plus 组件
     * Vite 插件 https://github.com/antfu/unplugin-vue-components
     * @param app {App}
    export default function styleImport(app) {
      const components = [ElLoading, ElMessage]
      components.forEach((v) => {
        app.use(v)
      return app
    

    在main.js使用

    import elemetPlusDirectives from './utils/element-plus-directive.js'
    const app = createApp(App)
    elemetPlusDirectives(app).mount('#app')