需求:
在某个 位置 动态的插入和删除自定义组件,比如点击切换页面内容
实现思想:
- 利用 React.createElement(), 创建或者引用自己定义的组件
- 利用 React.render() 真实渲染插入 自己的组件 dom
- 利用 React.unmountComponentAtNode(),销毁某个dom节点下的 react 组件节点
核心代码:
/** * 动态插入组件 * @param com com 可以是html 标签字符串,也可以是react class组件 或者是 函数组件 */ function loadComponent(com) { //获取要插入位置的节点 let container = document.getElementById('container你的dom id'); // 卸载之前组件 if(container) ReactDOM.unmountComponentAtNode(container) ReactDOM.render(React.createElement(com), container); }
参考demo:
1.定义的一些组件
AnalyzeMobxDevtools.tsx
function AnalyzeMobxDevtools(){ return ( <div>AnalyzeMobxDevtoolsAnalyzeMobxDevtoolsAnalyzeMobxDevtoolsAnalyzeMobxDevtoolsAnalyzeMobxDevtools</div> ) } export default AnalyzeMobxDevtools;
SyncUIStateObservable.tsx
function SyncUIStateObservable(){ return ( <div>SyncUIStateObservableSyncUIStateObservableSyncUIStateObservableSyncUIStateObservableSyncUIStateObservable</div> ) } export default SyncUIStateObservable;
2.归纳所有的组件到一个函数里,便于应用
代码结构

AllComponents.ts
import SyncUIStateObservable from './mobx/SyncUIStateObservable' import AnalyzeMobxDevtools from './mobx/AnalyzeMobxDevtools' /** * 所有的组件 ,用于页面切换 */ export default { "mobx": { 2: SyncUIStateObservable, 1: AnalyzeMobxDevtools }, "jsdesignpar":{ 0:1 } }
3.页面插入
app.tsx
import logo from './logo.svg'; import './App.css'; import { Layout, Menu, Breadcrumb } from 'antd'; import { UserOutlined, LaptopOutlined, NotificationOutlined } from '@ant-design/icons'; import ReactDOM from 'react-dom' import React from 'react' import AllComponents from './AllComponents' const { SubMenu } = Menu; const { Header, Content, Sider } = Layout; function App() { /** * 动态插入组件 * @param com */ function loadComponent(e: any) { let container = document.getElementById('container'); // 卸载之前组件 if(container) ReactDOM.unmountComponentAtNode(container) switch (e.item.props.datatype) { case 'mobx': const coms = AllComponents as any const typeComs = coms[e.item.props.datatype] ReactDOM.render(React.createElement(typeComs[e.key]), container); break; default: break; } } return ( <Layout style={{ height: "100%" }}> <Header className="header"> <div className="logo" /> <Menu theme="dark" mode="horizontal" defaultSelectedKeys={['2']}> <Menu.Item key="1">nav 1</Menu.Item> <Menu.Item key="2">nav 2</Menu.Item> <Menu.Item key="3">nav 3</Menu.Item> </Menu> </Header> <Layout > <Sider width={200} className="site-layout-background"> <Menu mode="inline" defaultSelectedKeys={['1']} defaultOpenKeys={['sub1']} style={{ height: '100%', borderRight: 0 }} > <SubMenu key="sub1" icon={<UserOutlined />} title="subnav 1"> <Menu.Item key="1" datatype="mobx" onClick={loadComponent}>option1</Menu.Item> <Menu.Item key="2" datatype="mobx" onClick={loadComponent}>option2</Menu.Item> <Menu.Item key="3" datatype="mobx" onClick={loadComponent}>option3</Menu.Item> <Menu.Item key="4" datatype="mobx" >option4</Menu.Item> </SubMenu> <SubMenu key="sub2" icon={<LaptopOutlined />} title="subnav 2"> <Menu.Item key="5">option5</Menu.Item> <Menu.Item key="6">option6</Menu.Item> <Menu.Item key="7">option7</Menu.Item> <Menu.Item key="8">option8</Menu.Item> </SubMenu> <SubMenu key="sub3" icon={<NotificationOutlined />} title="subnav 3"> <Menu.Item key="9">option9</Menu.Item> <Menu.Item key="10">option10</Menu.Item> <Menu.Item key="11">option11</Menu.Item> <Menu.Item key="12">option12</Menu.Item> </SubMenu> </Menu> </Sider> <Layout style={{ padding: '0 24px 24px' }}> <Breadcrumb style={{ margin: '16px 0' }}> <Breadcrumb.Item>Home</Breadcrumb.Item> <Breadcrumb.Item>List</Breadcrumb.Item> <Breadcrumb.Item>App</Breadcrumb.Item> </Breadcrumb> <Content className="site-layout-background" id="container" style={{ padding: 24, margin: 0, minHeight: 280, }} > Content </Content> </Layout> </Layout> </Layout> ); } export default App;
4.效果
