【问题标题】:Rendering Material-UI icons from an array从数组中渲染 Material-UI 图标
【发布时间】: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/

可能的解决方案:

  1. 将图标组件放入字符串中: { label: "Accounts", path: "/accounts" }, icon: "<AccountBox/>"} 但后来我需要以某种方式将字符串评估为 jsx。我不知道怎么做。

  2. 制作一个反应功能组件,根据道具呈现不同的图标,例如:<IconSwitch icon = {"accountIcon"} /> 并在 RFC 中硬编码不同的图标。不漂亮,但应该可以。

  3. 使用不同的图标,例如 svg 图标或字体图标,可以通过名称字符串引用。

关于如何做到这一点的任何建议? 谢谢

【问题讨论】:

  • { label: "Home", path: "/home", icon: <AccountBox/> } 不起作用吗?

标签: reactjs material-ui


【解决方案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>
                )

            })}
        </>
    )
}

【讨论】:

    猜你喜欢
    • 2018-11-22
    • 1970-01-01
    • 2016-10-29
    • 1970-01-01
    • 2021-10-14
    • 2021-08-28
    • 2019-03-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多