如何动态地将React组件插入DOM(例如对话框)?

时间:2016-07-13 01:11:43

标签: javascript reactjs

我想用一个处理相同任务的React组件替换内置在alert()函数中的javascript:即向用户显示快速,不允许的消息。

现在,我可以通过创建一个组件并将其放在我的标记中来实现这一点。例如

<div> 
    <BunchOfComponents />
    <MoreComponents />

    <MyAlertDialog open={this.props.shouldShowAlert} />
</div>

然后通过Redex或其他方式控制其open状态来显示它。

但是,我喜欢做什么,它能够在我的标记中声明它,而是注入它通过一个函数进入dom。

像...一样的东西。

myCoolFunction() {
    const alert = (
        <MyAlert
            open={true}
            msg="Hello World" 
        />
    )
    DOM.findNode('someID').insert(alert);  <-- fake API obviously   
}

是否可以动态附加这样的组件?

3 个答案:

答案 0 :(得分:2)

如果将其渲染为空节点,则可以在React渲染树中注入一些带有DOM操作的自定义内容。假设你在react的渲染中有某个地方:

import { provide } from '@angular/core';
import { LocationStrategy } from '@angular/common';
import { Router, ActivatedRoute } from '@angular/router';
import { addProviders } from '@angular/core/testing';
import { SpyLocation } from '@angular/common/testing';

class MockRouter {
  createUrlTree() {}
  navigateByUrl() {}
  navigate() {}
}

class MockActivatedRoute { }

beforeEach(() => {
  addProviders([
    {provide : Router useClass: MockRouter },
    {provide : ActivatedRoute,  useClass: MockActivatedRoute },
    {provide:LocationStrategy,  useClass: SpyLocation }
  ]);
});

然后,您可以按ID找到此节点,并为其<div id="you-know-id /> 分配一些内容。更“反应”的方式是使用refs而不是id。

通常情况下,这些内容会被包含在innerHTML(您插入的位置)和componentDidMount(您删除和取消订阅任何内容)方法中。

因为做肮脏的技巧你可能想避免内存泄漏。所以,就是这样。

顺便说一句,我认为这不是解决你刚才描述的问题的正确方法。你可以做什么,是这样的:

componentWillUnmount

然后在它打开时实际上挂载,并在它关闭时卸载。

但是,控制状态或道具成员的注射更安全。当你直接操作DOM时,你真的需要知道你在做什么。说,包装一些jQuery插件:)。那你很好,因为别无他法:)。

答案 1 :(得分:2)

这是我在工作中做的肮脏方式(听起来不对......) http://codepen.io/matthsiung/pen/JKOpVW

我确信有更好的“正确”方法,但它会自行清理,因此对我有用。

以下是要点:

对话框触发器

//Your trigger function will render the dialog component to a newly created dummy div,
// while also passing it into the component as a prop

function showDialog() {
  var div = document.createElement('div');
  ReactDOM.render(
     <Dialog container={div}/>,
     document.body.appendChild(div)
  );
} 

对话框组件:

//When your dialog component closes it unmounts itself
close(){
  ReactDOM.unmountComponentAtNode(this.props.container);
},

//Before unmount it cleans up after itself by removing the dummy div   
componentWillUnmount() {
 document.body.removeChild(this.props.container); 
},

答案 2 :(得分:1)

也许react-portal可以帮到你。

来自文档:

  

将其子项传输到新的React组件并将其附加到document.body(创建一个新的独立React树)

我经常使用(对话框/模态和菜单弹出窗口)。非常有用和轻量级。