You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现支持任意Props的Vue图标组件(含TS类型及简化调用)

实现支持直接传入图标名作为属性的Vue组件

核心思路

要实现<Icon navigate_next />这种调用方式,本质是让组件识别值为true的属性键作为图标名称,同时通过TypeScript类型定义实现图标名的自动提示。

方案1:单文件组件(SFC)实现

<template>
  <!-- 用$attrs绑定额外属性,支持自定义class、style等 -->
  <span class="material-symbols-outlined" v-bind="$attrs">
    {{ iconName }}
  </span>
</template>

<script setup lang="ts">
import { computed } from 'vue'

// 自定义Material图标名类型(可根据实际使用的图标集扩展)
type MaterialIconName = 
  'navigate_next' | 'home' | 'menu' | 'search' | 'settings';

// 定义Props:允许所有图标名作为可选布尔属性,同时兼容其他任意属性
type IconProps = {
  [K in MaterialIconName]?: boolean
} & Record<string, unknown> & {
  // 兼容原有name传参方式(可选)
  name?: string
}

const props = defineProps<IconProps>()

// 计算图标名称:优先取值为true的图标属性,其次兼容name传参
const iconName = computed(() => {
  // 找到值为true的图标属性键
  const matchedIcon = Object.keys(props).find(key => 
    props[key] === true && (key satisfies MaterialIconName)
  ) as MaterialIconName | undefined
  
  return matchedIcon || props.name || ''
})
</script>

方案2:TSX组件实现(非SFC)

import { defineComponent, computed } from 'vue'

type MaterialIconName = 
  'navigate_next' | 'home' | 'menu' | 'search' | 'settings';

type IconProps = {
  [K in MaterialIconName]?: boolean
} & Record<string, unknown> & {
  name?: string
}

export default defineComponent({
  setup(props: IconProps) {
    const iconName = computed(() => {
      const matchedIcon = Object.keys(props).find(key => 
        props[key] === true && (key as MaterialIconName)
      ) as MaterialIconName | undefined
      return matchedIcon || props.name || ''
    })

    return () => (
      <span class="material-symbols-outlined" {...props}>
        {iconName.value}
      </span>
    )
  }
})

使用示例

<!-- 目标调用方式 -->
<Icon navigate_next />

<!-- 同时传递额外属性 -->
<Icon home class="text-green-500" style="font-size: 24px" />

<!-- 兼容原有name传参方式 -->
<Icon name="search" />

类型优化(可选)

如果使用完整的Material Icons图标集,可安装官方类型包来自动提示所有图标名:

npm install @types/material-icons --save-dev

然后替换自定义的MaterialIconName为:

import type { MaterialIconName } from '@types/material-icons'

内容的提问来源于stack exchange,提问作者Archimedes Trajano

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 21:14:59