如何在 React 中附加到 dom?

IT技术 javascript reactjs
2021-03-24 19:02:07

这是一个 显示问题的 js 小提琴

在组件的渲染函数中,我渲染了一个带有 class 的 div .blahcomponentDidMount同一个组件功能中,我希望能够.blah像这样选择类并附加到它(因为组件已安装)

$('.blah').append("<h2>Appended to Blah</h2>");

但是,附加的内容不会显示。我还尝试(也显示在小提琴中)以相同的方式附加到子组件中,但结果相同,并且从子组件附加到父组件的空间中,结果相同。我尝试后者的逻辑是,可以更确定 dom 元素已被渲染。

同时,我能够(在componentDidMount函数中)getDOMNode附加到那个

 var domnode = this.getDOMNode(); 
 $(domnode).append("<h2>Yeah!</h2>")

然而,使用 CSS 样式的原因我希望能够将我知道的类附加到 div。此外,由于根据文档 getDOMNode已弃用,并且不可能使用替换getDOMNode来做同样的事情

 var reactfindDomNode = React.findDOMNode();
 $(reactfindDomNode).append("<h2>doesn't work :(</h2>");

我不认为getDOMNode或者findDOMNode是做我想做的事情的正确方法。

问题:是否可以在 React 中附加到特定的 id 或类?我应该使用什么方法来完成我想要做的事情(getDOMNode即使它已被弃用?)

var Hello = React.createClass({
    componentDidMount: function(){

       $('.blah').append("<h2>Appended to Blah</h2>");
       $('.pokey').append("<h2>Can I append into sub component?</h2>");
       var domnode = this.getDOMNode();
       $(domnode).append("<h2>appended to domnode but it's actually deprecated so what do I use instead?</h2>")

       var reactfindDomNode = React.findDOMNode();
       $(reactfindDomNode).append("<h2>can't append to reactfindDomNode</h2>");

    },
    render: function() {
        return (
            <div class='blah'>Hi, why is the h2 not being appended here?
            <SubComponent/>
            </div>
        )
    }
});

var SubComponent = React.createClass({

      componentDidMount: function(){
         $('.blah').append("<h2>append to div in parent?</h2>");
      },

      render: function(){
         return(
              <div class='pokey'> Hi from Pokey, the h2 from Parent component is not appended here either?            
              </div>
         )
      }
})

React.render(<Hello name="World" />, document.getElementById('container'));
3个回答

在 JSX 中,您必须使用className,而不是class. 控制台应显示有关此的警告。

固定示例:https : //jsfiddle.net/69z2wepo/9974/

您使用React.findDOMNode不当。你必须向它传递一个 React 组件,例如

var node = React.findDOMNode(this);

将返回组件本身的 DOM 节点。

然而,正如已经提到的,你真的应该避免在 React 之外改变 DOM。重点是根据组件的状态和props描述一次UI 然后更改状态或props以重新渲染组件。

是的。显然,如果你想使用一个不是 React 的组件,你必须找到一种方法让它工作。但是您自己不应该手动执行任何 DOM 更改。这是我集成 CodeMirror 的示例(公平地说,这很简单):github.com/fkling/exerslide/blob/master/components/Editor.js
2021-05-25 19:02:07
啊 d3... 是的,它也有例外,尤其是在涉及第三方库时。如果您搜索 React + d3,您会找到几种处理方法。
2021-05-27 19:02:07
如果你应该避免改变 dom,那么人们如何使用像 d3.js 这样附加到 dom 的库?不合适吗?
2021-05-28 19:02:07
例外?你是说应该避免改变 dom 的一般规则有例外吗?
2021-06-08 19:02:07
@BrainLikeADullPencil @Felix 你不应该改变React 管理的DOM 在你渲染 React 的元素之外改变 DOM 是完全可以接受的。如果您必须组件内部使用像 d3 这样的库,则可以将 append 附加到组件内部的元素上,只要每次状态更改时,您也以完全相同的方式应用 append。否则你的附加内容将被覆盖,并且当 React 重新渲染组件时你会看到不一致。另外,请记住,如果您操作托管 DOM,React 可能经常无故重新渲染
2021-06-10 19:02:07

避免在 react 中使用 jQuery,因为它有点反模式。我自己确实使用过它,但仅用于过于复杂或几乎不可能仅使用react组件的查找/读取。

无论如何,要解决您的问题,只需利用状态对象即可:

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <script src="https://fb.me/react-0.13.3.js"></script>

  </head>
  <body>
    <div id='container'></div>
    <script>
    'use strict';

var Hello = React.createClass({
    displayName: 'Hello',

    componentDidMount: function componentDidMount() {
        this.setState({
            blah: ['Append to blah'],
            pokey: ['pokey from parent']
        });
    },

    getInitialState: function () {
      return {
        blah: [],
        pokey: []
      };
    },

    appendBlah: function appendBlah(blah) {
        var blahs = this.state.blah;
        blahs.push(blah);
        this.setState({ blah: blahs });
    },
    render: function render() {
        var blahs = this.state.blah.map(function (b) {
            return '<h2>' + b + '</h2>';
        }).join('');
        return React.createElement(
            'div',
            { 'class': 'blah' },
            { blahs: blahs },
            React.createElement(SubComponent, { pokeys: this.state.pokey, parent: this })
        );
    }
});

var SubComponent = React.createClass({
    displayName: 'SubComponent',

    componentDidMount: function componentDidMount() {
        this.props.parent.appendBlah('append to div in parent?');
    },

    render: function render() {
        var pokeys = this.props.pokeys.map(function (p) {
            return '<h2>' + p + '</h2>';
        }).join('');
        return React.createElement(
            'div',
            { 'class': 'pokey' },
            { pokeys: pokeys }
        );
    }
});

React.render(React.createElement(Hello, { name: 'World' }), document.getElementById('container'));
    </script>
  </body>
</html>

抱歉 JSX 转换,但对我来说更容易测试而不设置 grunt :)。

无论如何,我正在做的是利用国家财产。当您调用 setState 时,将再次调用 render()。然后我利用 props 将数据传递给子组件。

它实际上不是我正在使用的 jquery,而是另一个具有 append 方法的库。(我假设您的解决方案仍然适用)。我只是将 jquery 用于这个问题,因为它说明了问题并且很容易在 jsfiddle 上设置..我会尝试你的答案并稍后接受
2021-06-03 19:02:07

这是您的 JSFiddle 的一个版本,我可以做的更改最少:JSFiddle

agmcleod 的建议是正确的——避免使用 JQuery。我想补充一点,避免 JQuery 思维,这花了我一段时间才弄明白。在 React 中,render 方法应该根据组件的状态渲染你想看到的东西。事后不要操纵DOM,操纵状态。当您更改状态时,组件将重新渲染,您将看到更改。

设置初始状态(我们没有附加任何东西)。

getInitialState: function () {
    return {
        appended: false
    };
},

更改状态(我们要追加)

componentDidMount: function () {
    this.setState({
        appended: true
    });
    // ...
}

现在渲染函数可以根据状态显示或不显示额外的文本:

render: function () {
    if (this.state.appended) {
        appendedH2 = <h2>Appended to Blah</h2>;
    } else {
        appendedH2 = "";
    }
    return (
        <div class='blah'>Hi, why isn't the h2 being appended here? {appendedH2}
        <SubComponent appended={true}/> </div>
    )
}
如果你应该避免改变 dom,那么人们如何使用像 d3.js 这样附加到 dom 的库?不合适吗?
2021-05-30 19:02:07
我不知道。我用过 d3.js 但没有用过 React。可以操作 DOM,但不应将其作为 React 组件的一部分进行操作
2021-06-03 19:02:07