Element Plus 图标:为什么有的需要 import,有的不需要?
先看两种常见的图标用法
<!-- 写法一:作为 prop 传值 -->
<el-button :icon="ArrowLeft">返回</el-button>
<!-- 写法二:作为子组件在 el-icon 容器内 -->
<el-icon><Check /></el-icon>
核心区别:ArrowLeft 作为对象传给 prop,Check 作为组件放进 el-icon 容器。
根本原因:两种用法,组件解析机制不同
写法一::icon="ArrowLeft" — prop 传组件对象
el-button 内部会直接使用 ArrowLeft 这个组件对象来渲染图标:
// el-button 内部伪代码
render() {
return h(Button, { icon: ArrowLeft }) // 直接用这个对象
}
如果没 import,ArrowLeft 就是 undefined,按钮里什么都没有。
:material-import-icon: 必须 import,否则图标不显示。
写法二:<el-icon><Check /></el-icon> — 动态组件容器解析
el-icon 是一个动态组件容器,它会从 Vue 的全局组件注册表里查找 Check:
// el-icon 内部伪代码
const iconName = 'Check' // 从子组件名拿到
const component = resolveComponent(iconName) // 从全局注册表查找
return h(component)
如果全局注册表里有 Check,就能找到并渲染。
你们项目为什么 Check 可以不 import?
看全局注册代码(src/components/SvgIcon/svgicon.js):
import * as components from '@element-plus/icons-vue'
export default {
install: (app) => {
for (const key in components) {
const componentConfig = components[key]
app.component(componentConfig.name, componentConfig) // 全局注册
}
}
}
项目启动时把所有 Element Plus 图标都全局注册了,所以 Check 出现在 <el-icon> 里时,el-icon 能从全局注册表找到它,不需要手动 import。
总结对比
| 用法 | 代码示例 | 是否需要 import | 原因 |
|---|---|---|---|
| prop 传图标 | :icon="ArrowLeft" |
:fontawesome-solid-check:{ .green } 必须 import | 需要组件对象本身 |
| el-icon 容器 | <el-icon><Check /></el-icon> |
:fontawesome-solid-xmark:{ .red } 不需要 | el-icon 从全局注册表查找 |
建议:统一风格,全部 import
两种写法混着来容易出错,而且:
- 全局注册会增加打包体积(虽然图标一般不大)
- 不 import 就用,代码可读性差(阅读者得去查全局注册才知道从哪来的)
- 容易漏掉导致 bug(哪天 el-icon 不从注册表找了,直接报错)
推荐统一写法,不管哪种用法都提前 import:
<script setup>
import { Check, ArrowLeft } from "@element-plus/icons-vue";
</script>
<template>
<!-- 两种写法都可以用,逻辑清晰 -->
<el-button :icon="ArrowLeft">返回</el-button>
<el-icon><Check /></el-icon>
</template>
最佳实践
代码一致性 > 代码量少。宁可多写一行 import,也让代码意图更明确。
如果项目图标用量大,建议把常用的图标抽取成一个公共文件集中管理:
// src/constants/icons.js
import { Check, ArrowLeft, Plus, Search } from "@element-plus/icons-vue";
export { Check, ArrowLeft, Plus, Search };
然后在需要的组件里:
import { Check, ArrowLeft } from "@/constants/icons.js";