二次封装 el-icon

1,605 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情。

简介

点赞 + 关注 + 收藏 = 学会了


这是一篇对日常工作没什么帮助的文章~

如果你还不太清楚 Element Plus 的 icon 是如何使用的,可以先阅读 《Element Plus 的 el-icon 到底怎么用》

Element UI 和 Element Plus 的 icon 用法是不一样的,在 Element Plus 中都改成了 svg 。

我在 《Element Plus 的 el-icon 到底怎么用》 里也对比过用法。


我习惯了 Element UI 的用法,但又喜欢用 Vue3 ,所以就在 Element Plus 的基础上二次封装了一个语法有点像 Element UI 里 icon 的组件出来。


虽然在我日常的 Vue3 项目中不会用本文所讲的这个组件,但我还是要搞出来。因为我真的好闲。



设计

要实现的功能

  1. 通过 type 属性使用指定的 svg 图标。
  2. size 属性传入 number 或者 string 都行,Element Plus 只支持 number,所以用的时候需要 v-bind:size="20" 这样写,或者用简写,但有时候还是会忘记加 v-bind,所以直接支持 size="20" 这样的字符串会更方便。
  3. type 属性支持首字母小写,Element Plus 使用的 svg 是大驼峰格式的,但有些短的单词有时候真的会忘记首字母大写。
  4. color 属性直接照搬回 Element Plus 的。

最终的使用方式

<e-icon type="Aim" :size="36" color="rgba(53, 131, 208, 0.5)" />

因为是二次封装,所以不能用回 <el-icon>,这是 Element Plus 的组件。

本次封装的目的是简化 icon 的使用方式,所以我把标签名也跟着简化了,变成 <e-icon>


缺点

打包出来的体积可能会大一丢丢。



开发

开发中涉及的技术点:

  1. 组件通讯
  2. 动态组件
  3. 全量引入 Element Plus 提供的 svg图标

本文的例子主要使用 props 的方式进行组件通讯。

如果你想了解更多 Vue3 的组件通讯方式,可以阅读 《Vue3 过10种组件通讯方式》


本例的代码比较简单,对应代码,跟着我的实现步骤来看。

以下是我的实现步骤:

  1. 全量引入 svg图标
  2. 引入 icon 样式
  3. 接收父组件传入的 size 、color 和 type
  4. 让 size 也兼容字符串类型(Element Plus 只支持 number)
  5. 图标名称首字母转大写
  6. 通过中括号的方式动态获取 svg图标
<template>
  <ElIcon :size="size2Number" :color="color">
    <!-- 动态组件 -->
    <component :is="currentIcon"></component>
  </ElIcon>
</template>

<script>
export default {
  name: 'EIcon'
}
</script>

<script setup>
import { computed } from 'vue'
import { ElIcon } from 'element-plus'
import * as Icons from '@element-plus/icons-vue' // 【步骤1】全量引入svg图标
import 'element-plus/es/components/icon/style/css' // 【步骤2】全量引入svg图标

// 【步骤3】接收父组件传入的 size、color 和 type
const props = defineProps({
  size: { // 图标尺寸
    type: [Number, String],
    default: 14,
    validator(value) {
      return !isNaN(value)
    }
  },
  color: { // 图标颜色
    type: String,
    default: 'inherit'
  },
  type: { // 图标类型
    type: String,
    default: ''
  }
})

// 【步骤4】size转换成数值型
const size2Number = computed(() => {
  if (isNaN(props.size)) {
    return 20
  }
  return Number(props.size)
})

// 【步骤6】动态获取图标
const currentIcon = computed(() => {
  let iconType = props.type
  let icon = null

  if (iconType !== '') {
    // 【步骤5】首字母大写
    icon = iconType.replace(iconType[0],iconType[0].toUpperCase())
  }

  return Icons[icon] // 通过中括号的方式动态获取
})
</script>

做这类组件,我通常会给组件一个 name,可以看到上面的代码是有 name 的,并且这个 script 没加 setup

<script>
export default {
  name: 'EIcon'
}
</script>


使用

在页面中引入并使用

<template>
  <div>
    <EIcon type="Aim" :size="36" color="rgba(53, 131, 208, 0.5)" />
  </div>
</template>

<script setup>
import EIcon from '@/components/EIcon/index.vue'
</script>

你也可以在 main.js 里 通过 app.use 全局注册该组件。



推荐阅读

👍《Element Plus 的 el-icon 到底怎么用?》

👍《Vue3 过10种组件通讯方式》

👍《Vue3 递归组件》

👍《Vite 搭建 Vue2 项目(Vue2 + vue-router + vuex)》

本例代码在这:e-icon