React组件名称动态化

3,055 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第23天,点击查看活动详情 

IMG_7996.GIF 上一节中我们介绍了虚拟dom,这一篇文章,我们根据虚拟dom思想,来讲解动态加载组件。

类似虚拟dom一样,假如我们想像VirtualDom一样,数据驱动页面。 根据穿进去的数据来动态加载对应组件。

需求

我们想根据数据加载对应dom页面 调用一个组件传进我们配置好的组件用type:表示对应的组件名称,参数name:则为传进组件中的参数。

<ComponentContainer itemsArray={[
    {type: 'ComponentA', name: '测试下传name1'},
    {type: 'ComponentB', name: '测试值name2'},
    {type: 'ComponentD', name: '测试值name4'},
    {type: 'ComponentC', name: '测试值name3'}]} className={'container'}/>

实现

方案一 require

const Component = require(`./${item.type}`).default;
<Component {...otherProps}></Component>

方案二

和方案一类似

import React, {lazy} from 'react';
const Component = lazy(() => import(`../a`));

方案二

1. 根据type新建对应的组件

ComponentA, ComponentB, ComponentD, ComponentC

a.js

import React from 'react';
// 我们解构传进来的参数,然后取到那么属性直接展示
export default function ComponentA({name}) {
    return <div>我是ComponentA{name}</div>
}

b.js ComponentB

import React from 'react';
// 我们解构传进来的参数,然后取到那么属性直接展示
export default function ComponentB({name}) {
    return <div>我是ComponentB{name}</div>
}

后面以此类推 c.js和 d.js

关键: 2. 新建index.d.ts文件导出所有我们需要动态加载的组件

export {default as ComponentA} from './a'
export {default as ComponentB} from './b'
export {default as ComponentC} from './c'
export {default as ComponentD} from './d'

最后取到组件并展示

import * as AllComponent from '../index'
type ComponentType = 'ComponentA' | 'ComponentB' | 'ComponentC' | 'ComponentD'
type ItemType =  {
    type: ComponentType
    name: string
}

interface Interface {
    items: ItemType[]
    className: string
}


// const Tag = require("antd")[type];
//
// if (!Tag) return false;
const ContainerComponent: FC<Interface> = ({items, ...otherProps}) => {
    return (
        <div {...otherProps}>
            我是container
            {items.map((itemConfig) => {
                const Component = AllComponent[itemConfig.type]
                return <Component {...itemConfig}/>
            })
            }

        </div>
}
export default QDForm

关键代码如下是,

  1. 第一行主要是导出所有组件得到字典对象AllComponent,
  2. 然后根据type取对应的组件。
  3. 赋值给常量Component。 jsx 的type不能为表达式,只能为变量

三步缺一不可。

import * as AllComponent from '../index'
const Component = AllComponent[itemConfig.type]

最终显示除了如下所示效果

image.png

IMG_7998.GIF

总结:显然第三种方式更优雅。通过import导入所有,然后取值,获取组件显示。 方案一一般不推荐require导包