通常我会通过直接导入来使用material-ui图标按照material-ui说明。
但是我有一个文本标签,它是实际的图标名称(如
calendar_view_day
),需要动态地从中获取和渲染图标组件。
我怎样才能像:
render() {
return (
<Icon name="calendar_view_day" color="primary" />
)
}
代替:
render() {
return (
<CalendarViewDay color="primary" /> // Imported by name
)
}
编辑 2:在使用以下内容之前,请先查看 @Roozbeh 在 2023 年中期关于使用字体材质图标的最新答案。
编辑1:这个答案适用于MUI v4,MUI v5答案如下(但未经我测试)
原来
material-ui
包含一个图标组件,允许您执行此操作...并且它本身会转换名称,因此接受 Snake、Pascal 和其他变体。 请注意,正如评论中指出的那样,这将大大增加捆绑包的大小。如果您的捆绑包大小受到限制,则必须采取不同的方法从某处提供图标 SVG!
import Icon from '@material-ui/core/Icon'
...
render() {
return (
<Icon>{props.iconName}</Icon>
)
}
创建函数:
...然后使用material-ui Icon组件。
这是代码:
import Icon from '@material-ui/core/Icon'
function upperFirst(string) {
return string.slice(0, 1).toUpperCase() + string.slice(1, string.length)
}
function fixIconNames(string) {
const name = string.split('_').map(upperFirst).join('')
if (name === '3dRotation') {
return 'ThreeDRotation'
} else if (name === '4k') {
return 'FourK'
} else if (name === '360') {
return 'ThreeSixty'
}
return name
}
...
render() {
const iconName = fixIconNames(props.iconName)
return (
<Icon>{props.iconName}</Icon>
)
}
MUI 5 开发人员在这里。
import * as Muicon from "@mui/icons-material";
const Icon = Muicon['SatelliteAlt']
<Icon fontSize="large" sx={{ px: 1 }}/>
打字稿
import * as MUIcon from "@mui/icons-material";
interface IconProps {
icon?: keyof typeof MUIcon;
}
const IconComp: React.FC<IconProps> = ({
icon,
}) => {
const Icon = icon && MUIcon[icon];
return ({Icon && <Icon />})
}
伙计们,快到 2024 年了,请使用字体材质图标。超轻量:
npm install material-icons@latest
在 JS 中导入(例如:Create React App 中的
src/index.js
、NextJS 中的src/_app.js
、Vue CLI 中的src/main.js
):
import 'material-icons/iconfont/material-icons.css';
在您的组件中:
import { Icon} from '@mui/material';
...
<Icon>{name}</Icon>
请注意图标名称是小写字母和下划线分隔
import React, {createElement } from "react";
import * as MuiIcons from "@material-ui/icons";
export default ({ iconName }) => (
<div>
{createElement(MuiIcons[iconName])}
</div>
);
<ComponentWithIcon iconName="Add" />
<ComponentWithIcon iconName="Anchor" />
这是一个组件,允许您像这样从字符串创建组件:
<MIcon name={'AccessAlarms'} sx={{ mr: 0.5 }}/>
打字稿中的组件:
import { IconTypeMap } from '@mui/material'
import * as MUIcon from '@mui/icons-material'
type IconProps = IconTypeMap['props']
interface MIconProps extends IconProps {
name: string | undefined
}
export default function MIcon(props: MIconProps) {
const { name } = props
const Icon = MUIcon[name as keyof typeof MUIcon]
if (Icon == null) {
throw `There is no "${name}" Icon`
}
return <Icon {...props} />
}
您可以从https://mui.com/material-ui/material-icons/
选择图标的名称此组件中还提供其他通用图标道具,例如
sx
。
如上面 thclark 的答案的评论中所述,使用 Icon 组件的解决方案将使用 Material-UI 图标的字体版本,该版本不包含完整的图标集。
通过使用相同的方法来获取正确的图标名称(借自 thclark)并结合 React.createElement 就可以了。我在 TypeScript 中做到了这一点,在普通 javascript 中甚至更容易。这里是 TS 版本的组件(dynamicIcon.tsx),也可以在 this repo:
import * as React from 'react';
import * as Icons from '@material-ui/icons/';
type IconType = typeof import('@material-ui/icons/index');
interface DynamicIconProps {
iconName: string,
className: string
}
function upperFirst(string:string) {
return string.slice(0, 1).toUpperCase() + string.slice(1, string.length)
}
function fixIconNames(string:string) {
const name = string.split('-').map(upperFirst).join('')
if (name === '3dRotation') {
return 'ThreeDRotation'
} else if (name === '4k') {
return 'FourK'
} else if (name === '360') {
return 'ThreeSixty'
}
return name;
}
export default class DynamicIcon extends React.Component<DynamicIconProps> {
constructor(props: DynamicIconProps) {
super(props);
}
render() {
return React.createElement(Icons[fixIconNames(this.props.iconName)! as keyof IconType], {className: this.props.className});
}
}
从 @mui 导入整个图标,将我的构建大小增加了 4MB,这不是我想要的,所以最后我像这样解决了它
import Icon from "@material-ui/core/Icon";
import * as React from "react";
import { Props } from "./types";
function cameltoSnakeCase(text = "") {
return text
.replace(/([A-Z])/g, "_$1")
.toLowerCase()
.slice(1);
}
const IconPresentation = ({ glyph, sx }: Props) => {
if (!glyph) return null;
return <Icon style={{ ...sx }}>{cameltoSnakeCase(glyph?.toString())}</Icon>;
};
export default IconPresentation;
你可以这样实现
import { SvgIconComponent } from '@mui/icons-material';
const MUIcon: { [key: string]: SvgIconComponent } = require('@mui/icons-material');
const CompA = () => {
const renderIcon = (iconName: string) => {
const Icon = MUIcon[iconName];
return (
{Icon && <Icon />}
)
}
}