我想为导入的组件动态创建JSX标记。所以我的想法是这样的:
import DemoComponent from './DemoComponent';
class DynamicRendering extends Component {
assembleResult() {
const {
democomponent
} = this.props;
const result = [];
if (democomponent) {
const Tag = `DemoComponent`;
result.push(<Tag />);
}
return result;
}
render() {
const result = this.assembleResult();
return result;
}
}
我的想法是,我可以将几个不同的道具传递给组件,然后组件动态创建JSX标签并将它们组合在一起。我想要这个的原因是因为我想要动态渲染大约15个组件。而不是隐式地写它们我宁愿在它们上面做一个循环,并在需要时动态创建它们。这样我可以保持这个组件DRY。
上面代码的问题在于,如果您创建这样的标记,它将把它作为HTML元素。这会导致错误,因为没有像'DemoComponent'这样的HTML元素。我设法通过创建道具名称到应该加载的组件的映射来解决这个问题。见下面的例子:
import DemoComponent from './DemoComponent';
const PROP_MODULE_MAP = new Map([
['democomponent', DemoComponent]
]);
class DynamicRendering extends Component {
assembleResult() {
const {
democomponent
} = this.props;
const result = [];
if (democomponent) {
const Tag = PROP_MODULE_MAP.get('democomponent');
result.push(<Tag />);
}
return result;
}
render() {
const result = this.assembleResult();
return result;
}
}
但我想知道是否有更简单的方法然后创建这个地图。还有另一种方法可以动态创建代表导入组件的JSX标记吗?
答案 0 :(得分:1)
您可以让父母传递所需的组件类型:
<强> Parent.js 强>:
import SomeComponent from './someComponent';
import Child from './child';
// the parent renders Child and passes the type SomeComponent as a prop
const Parent = () => <Child Elem={SomeComponent} />
<强> Child.js 强>:
// the Child renders the component type passed
// note that the prop "Elem" is capitalized so that it will not be treated as a html node
const Child = ({Elem}) => <Elem />;
export default Child;
这样Child
组件就能够呈现它传递的任何组件类型。这样更灵活,并且不需要Child
知道它应该在编译时呈现的所有组件。
请注意,在子项中呈现传递的组件类型时,要呈现的变量必须大写,否则它将被视为通常的html节点。有关详细信息,请参阅User-Defined Components Must Be Capitalized。
如果您不希望将prop名称大写,则可以在呈现它之前将值重新分配给子项中的大写名称:
const Child = ({elem: Elem}) => <Elem />;
答案 1 :(得分:0)
我不知道你的项目布局是什么,但我建议你可以做这样的事情:
在components
文件夹中为动态组件导入创建一个文件:
import Comp1 from './Comp1'
import Comp2 from './Comp2'
export default { Comp1, Comp2 }
为动态渲染的函数创建一个帮助器:
import components from './components/dynamic'
const renderComponents = compNames => {
// take compNames as a list
const compsToRender = compNames.map(name => components[name])
// get all components by compNames provided and return them in array
return compsToRender.map(Component => <Component />)
}
然后在你想要的地方打电话。
<App>
{renderComponents(['Comp1', 'Comp2'])}
</App>
如果你想传递带有组件名称的道具,你可以传递对象而不是字符串并将它们传递给函数内的组件,但我不明白为什么它会更好然后只使用带有props的普通组件