如何根据 JSON 配置动态渲染组件
介绍
React 使动态创建和渲染组件变得非常容易。它使我们能够使用现代 JavaScript 构建大型、快速的 Web 应用程序。对于 Facebook、Instagram 和许多其他公司的员工来说,它已经扩展得相当好。最酷的功能之一是,如果您不想使用 JSX(JavaScript 的模板扩展),则不必使用它。
在本指南中,我们将使用React.createElement()并根据 JSON 配置构建组件,而不是使用 JSX 来渲染组件。作为本指南的示例,我们将使用Reactstrap库并渲染卡片组件。
JSON 配置
让我们看一下 JSON 配置数据及其格式。
const CardConfig = {
component: "card",
children: [
{
component: "img",
src:
"https://images.pexels.com/photos/2877188/pexels-photo-2877188.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"
},
{
component: "body",
children: [
{
component: "title",
children: "This is a title"
},
{
component: "subtitle",
children: "This is the subtitle"
},
{
component: "text",
children:
"Some quick example text to build on the card title and make up the bulk of the card's content."
},
{
component: "button",
children: "Click Me!"
}
]
}
]
};
此 JSON 结构对应于组件在页面或屏幕上的嵌套和呈现方式。请注意,我在配置中添加了一个 component 键,以便我们可以将其映射到相应的 Reactstrap 组件。还有一个children键,它指定当前组件的所有子组件。它的值可以是字符串或组件数组。
除此之外,我们还可以有其他键作为 prop 传递给组件。例如,这里,图像组件中的src键将作为 prop 给出。
理想情况下,JSON 配置应按如下所示呈现。
<div class="card">
<img
src="https://images.pexels.com/photos/2877188/pexels-photo-2877188.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500"
class="card-img"
/>
<div class="card-body">
<div class="card-title">This is a title</div>
<div class="card-subtitle">This is the subtitle</div>
<p class="card-text">
Some quick example text to build on the card title and make up the bulk of
the card's content.
</p>
<button class="btn btn-secondary">Click Me!</button>
</div>
</div>
编写渲染器函数
要根据 JSON 配置中的组件键来呈现组件,我们首先需要创建一个将组件与组件键映射的对象。
const KeysToComponentMap = {
card: Card,
img: CardImg,
text: CardText,
body: CardBody,
title: CardTitle,
subtitle: CardSubtitle,
button: Button
};
如您所见,我已经将组件键与相应的 Reactstrap 组件进行了映射。
在顶部,我们将导入所有必需的组件。
import {
Card,
CardImg,
CardText,
CardBody,
CardTitle,
CardSubtitle,
Button
} from "reactstrap";
在renderer()函数中,我们首先检查KeysToComponentMap对象中是否存在该键。
const renderer = config => {
if (typeof KeysToComponentMap[config.component] !== "undefined") {
// ..
}
};
接下来我们将使用React.createElement()函数来渲染组件。
React.createElement()
React.createElement ()函数创建并返回给定类型的新 React 元素。
React.createElement(
type,
[props],
[...children]
);
它接受三个参数:type、props和children。
这里的类型是我们想要渲染的 React 组件;props是我们想要传递给组件的数据或属性,children是我们想要在 DOM 元素之间传递的另一个组件。
我们在 React 中编写的 JSX在 babel 编译器的帮助下被编译为React.createElement()函数调用。
我们来看一个简单的例子。
let WelcomeText = React.createElement(
"h1",
{ style: { color: "blue" } },
"This is a welcome text"
);
上面的代码在 DOM 中渲染为
<h1 style="color:blue">
This is a welcome text
</h1>
现在您已经了解了React.createElement()方法的工作原理,让我们回到最初的任务。
在createElement函数中,我们将传递要渲染的组件作为第一个参数,即KeysToComponentMap[config.component]。请注意,在这里访问对象时,我们使用括号[]表示法,而不是点.表示法。
function renderer(config) {
if (typeof KeysToComponentMap[config.component] !== "undefined") {
return React.createElement(KeysToComponentMap[config.component]);
}
}
括号[]表示法允许我们使用变量动态访问属性。因此,以这种方式获取组件更容易,而不是使用 switch case 块来确定要渲染哪个组件。
如果你运行我们目前的代码,你会注意到<Card />组件被渲染到 DOM 上。这意味着我们正朝着正确的方向前进。
<div class="card-container">
<div class="card"></div>
</div>
现在,让我们进一步行动,并渲染子组件。
我们需要检查子组件是否存在。然后映射每个子组件并将其传递给 renderer ()函数,使其递归。
config.children && config.children.map(c => renderer(c));
看起来不错。我们来试试吧。
function renderer(config) {
if (typeof KeysToComponentMap[config.component] !== "undefined") {
return React.createElement(
KeysToComponentMap[config.component],
{},
{
config.children && config.children.map(c => renderer(c))
}
);
}
}
糟糕!如果您收到错误config.children.map is not a function,请不要担心;这是因为并非所有子项都是数组类型,而我们没有考虑到这一点。例如,按钮组件有字符串类型的子项。所以让我们重写我们的条件。
function renderer(config) {
if (typeof KeysToComponentMap[config.component] !== "undefined") {
return React.createElement(
KeysToComponentMap[config.component],
{},
{
config.children &&
(typeof config.children === "string"
? config.children
: config.children.map(c => renderer(c)))
}
);
}
}
耶!我们让子组件进行渲染了。但是等等,我们还有一个图像组件没有显示出来。
为此,我们需要将src作为 prop 参数中的属性传递。
function renderer(config) {
if (typeof KeysToComponentMap[config.component] !== "undefined") {
return React.createElement(
KeysToComponentMap[config.component],
{
src: config.src
},
{
config.children &&
(typeof config.children === "string"
? config.children
: config.children.map(c => renderer(c)))
}
);
}
}
好了,我们已经成功从 JSON 配置动态渲染了一个组件。
完整源代码
<f
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~