Icon 图标
图标是按钮、列表项、状态提示等几乎所有组件的视觉零件。MIcon 只做一件事:把一个 24x24 viewBox 的 SVG path 字符串渲染成可着色、可缩放、可旋转的 SVG,颜色默认跟随 currentColor,因此放进任何容器都会自动继承文字色。
代码演示
基础用法
path 来自 @mdi/js,按需 import 单个图标常量即可,不会把整套图标打进产物。
点击任意图标会弹出提示。title 同时提供悬停提示与无障碍名称。
<script setup lang="ts">
import {
mdiBellOutline,
mdiCogOutline,
mdiContentCopy,
mdiDeleteOutline,
mdiMagnify,
mdiPencilOutline,
mdiRefresh,
mdiStarOutline,
} from '@mdi/js'
import { toast } from 'miao-design'
const icons = [
{ path: mdiPencilOutline, label: '编辑' },
{ path: mdiDeleteOutline, label: '删除' },
{ path: mdiContentCopy, label: '复制' },
{ path: mdiMagnify, label: '搜索' },
{ path: mdiCogOutline, label: '设置' },
{ path: mdiBellOutline, label: '通知' },
{ path: mdiRefresh, label: '刷新' },
{ path: mdiStarOutline, label: '收藏' },
]
function handleClick(label: string) {
toast.success(`点击了「${label}」图标`)
}
</script>
<template>
<div class="m-row-demo">
<MIcon
v-for="icon in icons"
:key="icon.label"
:path="icon.path"
:size="28"
:title="icon.label"
style="cursor: pointer"
@click="handleClick(icon.label)"
/>
</div>
</template>尺寸
size 传数字按 px 处理,传字符串则原样输出,可以用 em 这类相对单位跟随父级字号。
size 会同时写到 width、height 与 font-size 上。
<script setup lang="ts">
import { mdiCogOutline } from '@mdi/js'
const sizes = [16, 20, 24, 32, 40] as const
</script>
<template>
<div class="m-row-demo">
<!-- 数字按 px 处理 -->
<MIcon v-for="size in sizes" :key="size" :path="mdiCogOutline" :size="size" />
<!-- 字符串原样输出,可跟随父级字号 -->
<span style="font-size: 20px">
<MIcon :path="mdiCogOutline" size="1.5em" />
</span>
</div>
</template>语义色
六种语义色与主题令牌一一对应;不传 color 时继承 currentColor,disabled 使用禁用态文字色。
紫色的那个图标没有设置 color,颜色来自外层 span 的 color。
<script setup lang="ts">
import { mdiHeartOutline } from '@mdi/js'
const colors = ['primary', 'secondary', 'success', 'warning', 'error', 'info'] as const
</script>
<template>
<div class="m-row-demo">
<MIcon v-for="color in colors" :key="color" :path="mdiHeartOutline" :size="28" :color="color" />
<!-- 未指定 color 时继承 currentColor -->
<span style="color: #7e57c2">
<MIcon :path="mdiHeartOutline" :size="28" />
</span>
<MIcon :path="mdiHeartOutline" :size="28" disabled />
</div>
</template>翻转与旋转
flip 处理镜像,rotate 处理旋转,两者同时设置时会合并成一个 transform:先镜像再旋转。
第一行依次是原始、horizontal、vertical、both;第二行依次是 rotate 45 / 90 / 180 / 270 度。
<script setup lang="ts">
import { mdiArrowRight, mdiPencilOutline } from '@mdi/js'
const flips = ['horizontal', 'vertical', 'both'] as const
const rotates = [45, 90, 180, 270] as const
</script>
<template>
<div class="m-row-demo--col">
<div class="m-row-demo">
<MIcon :path="mdiPencilOutline" :size="30" title="原始" />
<MIcon v-for="flip in flips" :key="flip" :path="mdiPencilOutline" :size="30" :flip="flip" />
</div>
<div class="m-row-demo">
<MIcon :path="mdiArrowRight" :size="30" title="原始" />
<MIcon v-for="rotate in rotates" :key="rotate" :path="mdiArrowRight" :size="30" :rotate="rotate" />
</div>
</div>
</template>自旋
spin 用于加载、同步这类需要持续动效的场景。
开启 spin 后图标以 1.6s 线性循环旋转;系统开启「减少动态效果」时该动画会被禁用。
<script setup lang="ts">
import { mdiLoading, mdiRefresh, mdiSync } from '@mdi/js'
const spinning = [
{ path: mdiLoading, color: 'primary' },
{ path: mdiSync, color: 'success' },
{ path: mdiRefresh, color: 'info' },
] as const
</script>
<template>
<div class="m-row-demo">
<MIcon
v-for="item in spinning"
:key="item.color"
:path="item.path"
:size="28"
:color="item.color"
:spin="true"
:title="`${item.color} 加载中`"
/>
<!-- 静态对照 -->
<MIcon :path="mdiRefresh" :size="28" />
</div>
</template>API
Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
path | string | undefined | SVG path data,通常来自 @mdi/js;也可传入任意 24x24 viewBox 的单条 path d 字符串 |
size | number | string | 24 | 图标尺寸,数字按 px;字符串原样输出(如 '1.5em') |
color | 'primary' | 'secondary' | 'error' | 'success' | 'warning' | 'info' | undefined | 语义色;未提供时继承 currentColor |
disabled | boolean | false | 禁用态:使用 --m-action-disabled 文字色 |
flip | 'horizontal' | 'vertical' | 'both' | undefined | 翻转方向 |
rotate | number | 0 | 旋转角度(deg),正向为顺时针 |
spin | boolean | false | 自旋动画(加载、同步等场景) |
title | string | undefined | 无障碍可访问名称;缺省时图标对屏幕阅读器隐藏 |
Events
无。
Slots
无(不支持插槽内容,图标只渲染 path)。
类型定义
export type IconColor =
| 'primary' | 'secondary' | 'error' | 'success' | 'warning' | 'info'
export type IconFlip = 'horizontal' | 'vertical' | 'both'使用建议
图标名在 @mdi/js 里按需 import
MIcon 不内置任何图标,path 必须由使用方提供。安装 @mdi/js 后按需引入,避免整套图标进入产物:
npm i @mdi/js<script setup lang="ts">
import { MIcon } from 'miao-design'
import { mdiPencilOutline } from '@mdi/js'
</script>
<template>
<MIcon :path="mdiPencilOutline" :size="20" color="primary" title="编辑" />
</template>图标检索页 可以按名称搜索并直接复制常量名。
组件上挂的点击事件会落到 svg 上
MIcon 没有声明 emits,所以 @click 这类监听器会作为普通属性透传到根 <svg> 上。做可点击图标时建议外面套一层 MButton,语义与焦点行为更完整。
只支持单条 path
组件内部只渲染一个 <path :d="path">。需要多路径的图标(例如带镂空的组合图形)要自己用内联 <svg> 写,或者换一个单路径的图标。
path 为空不会报错
path 为空时组件渲染一个占位 <svg class="m-icon--placeholder">(透明、不占视觉),而不是抛错或警告。图标没显示出来时,先确认 @mdi/js 的常量名拼写与 import 是否漏了。