React使用动态标签名称

最近在一项目里(React + antd)遇到一个需求,某项基础信息里有个图标配置(图标用的是antd的Icon组件),该项基础信息的图标信息修改后,存于后台数据库,后台数据库里存的是antd Icon组件的图标Tag名称,如AreaChartOutlined PieChartOutlined BarChartOutlined 等,另外在展示页面,需要根据该项信息的Tag名称,显示对应的antd图标。

antd 图标的使用方法

正常情况下安装@ant-design/icons依赖后,就可以在页面中使用antd图标,如:

shell 复制代码
$ npm install @ant-design/icons --save
ts 复制代码
import { HomeOutlined } from '@ant-design/icons';

const App: React.FC = () => (
  <Space>
    <HomeOutlined />
  </Space>
);

但是如果页面中,图标的Tag名称不确定,又如何使用呢?

方案1. 使用React.createElement创建元素

关于React.createElement的详细用法,可以阅读文档:https://react.dev/reference/react/createElement
React.createElement(type, props, ...children) 包含三个参数:

  • type: 该参数必须为一个有效的React组件类型,例如,其可以是一个Tag名称(如div或者span),也可以是一个React组件(一个函数、一个类或者一个特殊组件如Fragment)
  • props: 该参数应是一个对象或者null。如果传递null,则会当成空对象处理。React会创建一个元素,该元素属性与参数props相匹配。
  • optional ...children: 可选参数children。可以传递0个、1个或多个。其可以是ReactNode,包含React组件,字符串,数字,ReactNode,空节点(null, undefined, true, false),或者ReactNode数组。

知道React.createElement用法之后,我们可以进行简单的尝试,代码如下:

ts 复制代码
import React from "react";
import "./index.css";
import * as Icons from "@ant-design/icons"; // 注意要先引入icons
import { Space } from "antd";

function customIcon(tagName: string) {
  return React.createElement(Icons[tagName], {}, null);
}

const App: React.FC = () => (
  <Space>
    {customIcon("AreaChartOutlined ")}
    {customIcon("PieChartOutlined  ")}
    {customIcon("BarChartOutlined  ")}
  </Space>
);

export default App;

完整代码可以在codesandbox里查看:https://codesandbox.io/p/sandbox/react-createelement-chuang-jian-dong-tai-yuan-su-3hndf2?file=%2Fdemo.tsx%3A1%2C1

在codesandbox里我们可以看到,效果和我们预想的一样,正常显示了三个图标:

使用自定义Tag Name

但是对于上述方法,个人感觉有一点点的繁琐。

在一番搜索之下,看到React官方文档里有这么一句话:(链接:https://legacy.reactjs.org/docs/jsx-in-depth.html#user-defined-components-must-be-capitalized

When an element type starts with a lowercase letter, it refers to a built-in component like
or and results in a string 'div' or 'span' passed to React.createElement. Types that start with a capital letter like compile to React.createElement(Foo) and correspond to a component defined or imported in your JavaScript file.

大意是说Tag名称如果以小写 开头,则会指向内置的html组件,例如<div> 或者 <span>,结果将会通过React.createElement创建对应元素,其中type参数为'div'或者'span',如: React.createElement('div');如果Tag名称如果以大写 开头,例如<Foo />,结果则会通过React.createElement(Foo)创建对应的元素,对应的组件则必须在js文件中引入。(这段翻译是我瞎掰的,手动狗头)。

所以我们可以将上面代码中的customIcon方法简化如下:

ts 复制代码
function customIcon(tagName: string) {
  const Icon = Icons[tagName]; // 变量名必须以大写字母开头
  return <Icon />;
}

完整代码如下:

ts 复制代码
import React from "react";
import "./index.css";
import * as Icons from "@ant-design/icons"; // 注意要先引入icons
import { Space } from "antd";

function customIcon(tagName: string) {
  // return React.createElement(Icons[tagName], {}, null);
  const Icon = Icons[tagName]; // 变量名必须以大写字母开头
  return <Icon />;
}

const App: React.FC = () => (
  <Space>
    {customIcon("AreaChartOutlined")}
    {customIcon("PieChartOutlined")}
    {customIcon("BarChartOutlined")}
  </Space>
);

export default App;

完整代码可以在codesandbox里查看:https://codesandbox.io/p/sandbox/custom-tag-name-h7zhyt?file=%2Fdemo.tsx%3A1%2C1

在codesandbox里我们可以看到,效果和之前的效果一模一样,都是显示三个图标。

扩展阅读:
2022年中华人民共和国县以上行政区划代码
react + antd实现动态切换主题功能(适用于antd5.x版本)
常用的几款Vue移动端UI推荐

相关推荐
桂月二二6 小时前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
hunter2062067 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb7 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角7 小时前
CSS 颜色
前端·css
九酒8 小时前
从UI稿到代码优化,看Trae AI 编辑器如何帮助开发者提效
前端·trae
浪浪山小白兔9 小时前
HTML5 新表单属性详解
前端·html·html5
lee5769 小时前
npm run dev 时直接打开Chrome浏览器
前端·chrome·npm
2401_897579659 小时前
AI赋能Flutter开发:ScriptEcho助你高效构建跨端应用
前端·人工智能·flutter
limit for me10 小时前
react上增加错误边界 当存在错误时 不会显示白屏
前端·react.js·前端框架
浏览器爱好者10 小时前
如何构建一个简单的React应用?
前端·react.js·前端框架