我正在编写一个反应应用程序,它是金融交易应用程序的瘦客户端UI。核心要求是应用程序必须完全动态且可配置,包括表格。具体来说,我有一些贸易录入表格,需要在服务器端定义并存储在数据库中,以便在客户端上动态呈现,但是布局很重要,并且需要能够支持多种不同格式。我见过一些采用JSON表单架构并从其中创建静态表单的库,但是它们似乎都不支持我所需的那种布局灵活性。例如,我需要支持组件的选项卡,列和行。我的问题是-有人可以建议一个可以做我要找的ReactJs库吗?如果没有,我将如何自己实施?
这是一个更具体的例子;假设我有一个通过REST调用从服务器获取的架构,如下所示:
{
title: "Securities Finance Trade Entry",
children: [
{
containerType: "tabs",
children: [
{
title: "Common",
children: [
{
containerType: "row",
children: [
{
input: "ComboBox",
label: "Trade Type",
options: ["Repo", "Buy/Sell", "FeeBased"]
},
{
input: "ComboBox",
label: "Direction",
options: ["Loan", "Borrow"]
}
]
},
{
containerType: "row",
children: [
{
containerType: "column",
children: [
{
containerType: "row",
children: [
{
input: "text",
label: "Book"
},
{
input: "text",
label: "Counterparty"
}
]
},
{
containerType: "row",
children: [
{
input: "date",
label: "StartDate"
},
{
input: "date",
label: "EndDate"
}
]
},
{
containerType: "row",
children: [
{
input: "text",
label: "Security"
},
{
input: "numeric",
label: "Quantity"
}
]
}
]
}
]
}
]
}
]
}
]
}
我希望渲染以下内容: 基本上,在该架构中,仅会显示一个选项卡,但可能会有多个选项卡,每个选项卡在行和列中都包含多个子项,并且也可能包含嵌套的选项卡容器。如果我自己做出反应,我会考虑使用.map遍历json和一些if语句,以在适当的地方插入标签。但是,项目需要嵌套,所以我不知道如何渲染它,以使所选标签是动态的并且可以有子级...例如,我可以这样写: {如果(container.containerType ===“ column”){()},但随后我需要以某种方式将其余控件嵌入该标记中,我认为我不能在结尾处仅发出() ...
我考虑过的另一个选项是将上述json转换为服务器端的JSX并将其发送。在Java服务器端编写一个解析器将上述json转换为JSX文档并将其返回给客户端将是相当容易的,但是我将如何呈现它呢?有什么办法可以做类似的事情:
onComponentMount() {
fetch(webserviceUrl + 'getJsxForForm/' + props.formName)
.then(result => {this.setState({form : result});
}
render() {
return ({this.state.form});
}
但是,再次,我认为这行不通。如果我从服务器获取文档,它将以纯文本形式呈现,而实际上没有将其转换为有效的html,对吧?
那么,我有什么选择?我正在寻找可以做到这一点的现有库的建议,或者关于我提到的其他两种方法(它们会行得通吗,我怎么做?)的建议,或者其他想法。 谢谢, 特洛伊
答案 0 :(得分:3)
我喜欢从某种JSON配置动态呈现页面的概念。
键将定义Components
以匹配containerTypes
和inputs
,然后通过递归函数遍历JSON
配置。在您的JSON
配置中,建议您在希望呈现组件的任何地方使用组件命名约定。因此,大写Tabs
,Row
,Column
等
这里是该功能的一个示例。注意,在每个containerType
组件中,都有一个对此函数的调用,其中传递了children
。
看这支笔:https://codepen.io/wesleylhandy/pen/oQaExK/
示例组件:
const Container = props => {
return (
<div className="container">
<h1>{props.title}</h1>
{renderChildren(props.children)}
</div>
)
}
递归式子级渲染示例
const renderChildren = children => {
return children ? children.map((child, ind) => {
const newChildren = child.children ? [...child.children] : [];
const {containerType, title, input, label, options} = child
let key;
if (newChildren.length) {
key = `${containerType}-${ind}`;
switch (containerType) {
case "Tabs":
return <Tabs
key={key}
title={title}
children={newChildren}
/>
case "Column":
return <Column
key={key}
title={title}
children={newChildren}
/>
case "Row":
return <Row
key={key}
title={title}
children={newChildren}
/>
default:
return <Common
key={key}
title={title}
children={newChildren}
/>
}
} else {
key=`${input}-${ind}`
switch (input) {
case "ComboBox":
return <SelectGroup
key={key}
label={label}
options={options}
/>
case "Text":
case "Date":
case "Numeric":
return <InputGroup
key={key}
label={label}
type={input}
/>
}
}
}) : null
}