Vue 3 使用 Element Plus 组件自动导入

使用 Vue 3 配合 Element Plus 进行 App 开发是一种很流行的搭配,我也选择了这对组合,此前并不了解前端开发,所以我按照文档进行操作。在全部导入和按需导入里,我选择了感觉会比较精益的按需导入模式。不过,文档在这方面的介绍并不全面。

全部导入

typescript 复制代码
// 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')

这是官方文档中提供的全部导入的方法。通过这种方法,我们可以安全的在整个项目的所有地方,使用 Element UI 的组件,不用担心引用和样式的问题。后来我才知道,这可能是一种更好的选择,如果你急功近利想要完成项目,这种方法可能是一种问题比较少的方法。

按需导入

按需导入,分为自动导入和手动导入两种,其中手动导入是比较麻烦的,每用到一个组件,都需要手动 import 这个组件用到的代码和样式,非常麻烦,我直接就跳过了没看。选了利用插件支持的自动导入方法,需要额外的插件支持:

shell 复制代码
npm install -D unplugin-vue-components unplugin-auto-import

这也是官方比较推荐的方法,Vite 的配置如下:

typescript 复制代码
// 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()],
    }),
  ],
})

不得不说,整个开发体验非常好,到这里,多数情况下引用 Element UI 组件,都很方便,直接写代码就行。不过,仍然有一些,每个人都难免遇到的情况,这个文档没有详细介绍,应该怎么处理。

遇到的问题

我们都知道,一个 Vue 组件 SFC,包含三个部分,<template><script><style>,我发现,在实际使用中,一般来说,引用 Element UI的话,我们都会写在这个 <template> 里面。比如:

typescript 复制代码
<template>
  <el-tree />
</template>

在这种情况下,上文提到的自动导入方案,都会很好地工作。但是,有时候,你会发现,你不止会在 <template> 里面使用到组件。比如,我昨天就撰文说了那个奇怪的问题,就是一种情况。

typescript 复制代码
<script lang="ts" setup>
const treeRef = ref<InstanceType<typeof ElTree>>(null)
</script>
<template>
  <el-tree
    ref="treeRef"
   />
</template>

在上面这个代码案例里,我们因为某种原因,需要一个 ElTree 组件的引用,好在代码里操作它,如果你用了 TypeScript 的情况下,如果不声明引用的类型,那么 ElTree 上带有的方法,是不会在 IDE 里提示的,甚至你调用了,还会报错。因为 IDE 提示,不能在 never 类型上使用该方法。虽然说,可能执行的时候是不会有错的,但是你连编译这关可能都过不了。

(所以说,尽量不要选择 TypeScript 除非真的有这个需要,或者跟我一样轴)

但是,这时候我就发现,在 <script> 里出现的 ElTree 的名字,上面提到的自动导入,并不能自动解决。尤其这种在泛型括号里出现的组件名字。解决这种情况方法,昨天的文章我也提及了:

typescript 复制代码
<script lang="ts" setup>
import type { ElTree } from "element-plus"
</script>

注意上面代码里的 type 这四个字母,如果你去掉,也不会报错,那样就是你直接导入组件而不是导入类型。导入组件,是有副作用的,会导致这个页面的 tree 组件样式缺失。具体原理我这会儿还没懂,大体上就是在自动导入的环境下,你如果手动导入了,会出冲突。

另一个案例

除了这个情况,还有一种情况,你会遇到在 <script> 里出现组件的情况,那就是那些默认没有模版,全动态使用的组件,比如 ElMessageBox 和 ElMessage。

typescript 复制代码
<script lang="ts" setup>

function callMsg() {
  ElMessageBox.confirm(
    "一旦执行不可撤销,是否继续?",
    "注意",
    {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning"
    }
  }
}
</script>

上面是一个使用的例子,在这个例子里,一开始介绍的按需自动导入,也不会生效。这种情况,还不同于上一种情况,不是出现在类型泛型的尖括号里,而是出现在代码里,这里导入 type 是不行的。我们需要在 vite 的自动导入配置里加入一个 eslint 有关的配置:

typescript 复制代码
// 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({
      eslintrc: {
        enabled: true
      },
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
})

注意 13-15 行,这行配置会导致插件自动生成一个文件 .eslintrc-auto-import.json 这个文件,文件名是可以用参数指定自定义的,就不演示了。这个文件在目录下形成后,还要把这个文件告知给 eslint 才能起作用。

javascript 复制代码
//.eslintrc.cjs
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')

module.exports = {
  root: true,
  extends: [
    'plugin:vue/vue3-essential',
    'eslint:recommended',
    '@vue/eslint-config-typescript',
    '@vue/eslint-config-prettier/skip-formatting',
    './.eslintrc-auto-import.json'
  ],
  parserOptions: {
    ecmaVersion: 'latest'
  },
  ignorePatterns: ['main.js', 'preload.js']
}

注意上面的第 12 行,把新自动生成的文件,加入了配置。除了上述文件,根目录下还有生成一个文件 auto-imports.d.ts 文件,还要将这个文件告知给 ts:

json 复制代码
//tsconfig.json
{
  "extends": "@vue/tsconfig/tsconfig.dom.json",
  "include": ["env.d.ts", "src/**/*", "src/**/*.vue", "./auto-imports.d.ts"],
  "exclude": ["src/**/__tests__/*"],
  "compilerOptions": {
    "composite": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    },
    "types": ["@modyfi/vite-plugin-yaml/modules"]
  }
}

注意第 4 行的最后,加入了这个文件,作为一个 include 文件,到此,此种情况就不会再报错了。

结论

这种很重要,而且几乎人人会遇到的情况,官方文档竟然缺失,这让人很遗憾,作为一个小白,我遇到了就是全网到处乱找,而不少文章都是告诉我,遇到了就改成本文第一节提到的方法,改为全量导入。

如果按需导入根本不能解决问题,那么又有什么存在的必要呢?其实我现在还是有点一知半解,为什么我介绍的关于 ElTree 的那种情况,我介绍的这个关于 eslint 和 ts 的配置也解决不了。这些无数人使用的插件都是大漏勺么?随便就漏掉一些很常见的问题的处理。

相关推荐
cs_dn_Jie1 小时前
钉钉 H5 微应用 手机端调试
前端·javascript·vue.js·vue·钉钉
开心工作室_kaic2 小时前
ssm068海鲜自助餐厅系统+vue(论文+源码)_kaic
前端·javascript·vue.js
有梦想的刺儿2 小时前
webWorker基本用法
前端·javascript·vue.js
customer083 小时前
【开源免费】基于SpringBoot+Vue.JS周边产品销售网站(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·开源
上海_彭彭4 小时前
【提效工具开发】Python功能模块执行和 SQL 执行 需求整理
开发语言·python·sql·测试工具·element
getaxiosluo4 小时前
react jsx基本语法,脚手架,父子传参,refs等详解
前端·vue.js·react.js·前端框架·hook·jsx
理想不理想v4 小时前
vue种ref跟reactive的区别?
前端·javascript·vue.js·webpack·前端框架·node.js·ecmascript
栈老师不回家5 小时前
Vue 计算属性和监听器
前端·javascript·vue.js
前端啊龙5 小时前
用vue3封装丶高仿element-plus里面的日期联级选择器,日期选择器
前端·javascript·vue.js
小远yyds6 小时前
前端Web用户 token 持久化
开发语言·前端·javascript·vue.js