从数组中渲染 Material-UI 图标
Posted
技术标签:
【中文标题】从数组中渲染 Material-UI 图标【英文标题】:Rendering Material-UI icons from an array 【发布时间】:2021-02-19 17:49:06 【问题描述】:背景信息: 我正在使用 react 和 material-ui。 为了保持代码干净,我从一个 const 数组中填充菜单项,如下所示:
const menuItems = [
label: "Home", path: "/home" ,
label: "Accounts", path: "/accounts" ,
label: "Organizations", path: "/organizations" ,
];
数组中的每一项都是一个包含标签和重定向路径的对象。我在渲染时映射项目。非常基础。
问题: 我想在 menuItems 数组中包含一个 material-ui 图标组件,以便可以在标签旁边呈现图标。但我找不到通过名称字符串引用图标的方法https://material-ui.com/components/material-icons/
可能的解决方案:
将图标组件放入字符串中:
label: "Accounts", path: "/accounts" , icon: "<AccountBox/>"
但后来我需要以某种方式将字符串评估为 jsx。我不知道怎么做。
制作一个反应功能组件,根据道具呈现不同的图标,例如:<IconSwitch icon = "accountIcon" />
并在 RFC 中硬编码不同的图标。不漂亮,但应该可以。
使用不同的图标,例如 svg 图标或字体图标,可以通过名称字符串引用。
关于如何做到这一点的任何建议? 谢谢
【问题讨论】:
label: "Home", path: "/home", icon: <AccountBox/>
不起作用吗?
【参考方案1】:
图标字体
您可以使用Icon
组件。 https://material-ui.com/components/icons/#icon-font-icons
要使用图标,只需将图标名称(字体连字)与 Icon 组件包装起来,例如:
import Icon from '@material-ui/core/Icon'; <Icon>star</Icon>
https://codesandbox.io/s/material-demo-forked-sj66h?file=/demo.tsx
假设您使用适当的图标连字设置菜单项:
const menuItems = [
label: "Home", path: "/home", icon: "home" ,
label: "Accounts", path: "/accounts", icon: "account_circle" ,
label: "Organizations", path: "/organizations", icon: "settings"
];
然后你可以映射它们:
menuItems.map(( label, icon ) =>
return (
<span key=label>
label <Icon>icon</Icon>
</span>
);
)
SVG 图标
如果您想使用 SVG 图标而不是基本图标,我建议您只提取您计划使用的 SVG 图标,以便从生成的捆绑包中对您不使用的图标进行树状抖动。摇树的能力是使用 SVG 图标而不是字体图标的一个很好的理由。
import Home, AccountCircle, Settings, AddCircle from "@material-ui/icons";
如果您想允许用户输入所有图标或事先不知道将显示哪些图标,您可以从@material-ui/icons
导入所有内容,如Jonathan's answer。
如果您没有将图标列表放入需要能够被字符串化的东西(即 Redux/通过 API 调用发送),那么您可以直接将图标放入数组并渲染它们:
const menuItems: MenuItem[] = [
label: "Home", path: "/home", icon: <Home /> ,
label: "Accounts", path: "/accounts", icon: <AccountCircle /> ,
label: "Organizations", path: "/organizations", icon: <Settings />
];
// Rendering:
menuItems.map(( label, icon ) =>
return (
<span key=label>
label icon
</span>
);
)
如果您要将图标放在需要字符串化的地方,上述方法将不起作用,因此我建议将您要使用的图标放入对象中以映射它们。这样你就有一个字符串到图标映射。
示例:https://codesandbox.io/s/material-icons-svg-udcv3?file=/demo.tsx
import Home, AccountCircle, Settings, AddCircle from "@material-ui/icons";
const icons =
Home,
AccountCircle,
Settings
;
在上面的例子中(即从数组中渲染图标)
interface MenuItem
label: string;
path: string;
icon: keyof typeof icons;
const menuItems: MenuItem[] = [
label: "Home", path: "/home", icon: "Home" ,
label: "Accounts", path: "/accounts", icon: "AccountCircle" ,
label: "Organizations", path: "/organizations", icon: "Settings"
];
// Rendering:
menuItems.map(( label, icon ) =>
const Icon = icons[icon];
return (
<span key=label>
label <Icon />
</span>
);
)
【讨论】:
太棒了。这行得通。只需在 index.html 文件中包含<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
即可获取 Material Icons 字体。 --- 谢谢!
这适用于某些但并非适用于所有图标。见:material-ui.com/components/icons/…。例如,Brightness3Rounded
图标似乎不包含在字体中
@Jonathan 感谢您的提醒。我已更新以包含一些其他允许使用 SVG 图标的方法【参考方案2】:
您可以从@material-ui/icons
导入所有内容,然后动态创建图标组件:
import React from 'react'
import * as icons from '@material-ui/icons'
interface MenuItem
label: string,
icon: keyof typeof icons,
path: string
export function Menu()
const menuItems: MenuItem[] = [
label: 'Home', path: './home', icon: 'Home' ,
label: 'Accounts', path: './accounts', icon: 'AccountCircle' ,
label: 'Organizations', path: './organizations', icon: 'Settings'
]
return (
<>
menuItems.map(menuItem =>
const Icon = icons[menuItem.icon]
return (
<span key=menuItem.path>
menuItem.label <Icon />
</span>
)
)
</>
)
【讨论】:
以上是关于从数组中渲染 Material-UI 图标的主要内容,如果未能解决你的问题,请参考以下文章
ReactJS with Material-UI:如何按字母顺序对 Material-UI 的 <TableRow> 数组进行排序?
无法在我的导航菜单中显示实际的 Material-ui 图标