应该有一个容器将组件名称映射到所有应该动态使用的组件。组件类应该在容器中注册,因为在module化环境中,否则没有可以访问它们的单一位置。组件类不能在没有明确指定的情况下通过它们的名称来识别,因为功能name
在生产中被缩小了。
组件图
它可以是普通对象:
class Foo extends React.Component { ... }
...
const componentsMap = { Foo, Bar };
...
const componentName = 'Fo' + 'o';
const DynamicComponent = componentsMap[componentName];
<DynamicComponent/>;
或者Map
例如:
const componentsMap = new Map([[Foo, Foo], [Bar, Bar]]);
...
const DynamicComponent = componentsMap.get(componentName);
普通对象更合适,因为它受益于属性简写。
枪管module
一筒module与命名出口可以充当这样的地图:
// Foo.js
export class Foo extends React.Component { ... }
// dynamic-components.js
export * from './Foo';
export * from './Bar';
// some module that uses dynamic component
import * as componentsMap from './dynamic-components';
const componentName = 'Fo' + 'o';
const DynamicComponent = componentsMap[componentName];
<DynamicComponent/>;
这适用于每个module代码样式的一个类。
装饰器
装饰器可以与类组件一起使用以获得语法糖,这仍然需要明确指定类名并将它们注册到映射中:
const componentsMap = {};
function dynamic(Component) {
if (!Component.displayName)
throw new Error('no name');
componentsMap[Component.displayName] = Component;
return Component;
}
...
@dynamic
class Foo extends React.Component {
static displayName = 'Foo'
...
}
装饰器可以用作具有功能组件的高阶组件:
const Bar = props => ...;
Bar.displayName = 'Bar';
export default dynamic(Bar);
使用非标准displayName
而不是随机属性也有利于调试。