应该有一个容器,用于将组件名称映射到所有应该动态使用的组件。组件类应该在容器中注册,因为在模块化环境中,否则没有单个位置可以访问它们。如果不明确指定组件类,则无法通过它们的名称来标识它们,因为函数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);
普通对象更适合,因为它受益于属性速记。
机筒模块
一筒模块与命名出口可以充当这样的地图:
// 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/>;
每个模块代码样式一个类都可以很好地工作。
装饰器
装饰器可以与语法糖的类组件一起使用,这仍然需要明确指定类名称并将其注册在映射中:
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
而不是随机属性也有利于调试。
{...this.props}
有用的方法,可以将道具透明地传递给父对象的子类型组件。喜欢return <MyComponent {...this.props} />