从数组中渲染 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 文件中包含 &lt;link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" /&gt; 即可获取 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 图标的主要内容,如果未能解决你的问题,请参考以下文章

生产/构建中的 Material-UI 渲染错误

ReactJS with Material-UI:如何按字母顺序对 Material-UI 的 <TableRow> 数组进行排序?

无法在我的导航菜单中显示实际的 Material-ui 图标

React Material-UI 下拉菜单不起作用

如何使用带有 material-ui 图标组件的自定义 SVG 文件?

如何在 Material-ui 的 TableSortText 组件中自定义彩色文本和图标?