【问题标题】:How to append to dom in React?如何在 React 中附加到 dom?
【发布时间】:2015-06-09 01:54:46
【问题描述】:

Here's a js fiddle 显示实际问题。

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

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

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

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

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

然而,与 CSS 样式有关的原因我希望能够使用我知道的类附加到 div。另外,由于根据docs 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'));

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

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

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

    您错误地使用了React.findDOMNode。您必须将 React 组件传递给它,例如

    var node = React.findDOMNode(this);
    

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

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

    【讨论】:

    • 如果你应该避免改变 dom,那么人们如何使用像 d3.js 这样附加到 dom 的库?不合适吗?
    • 啊 d3... 是的,它也有例外,尤其是在涉及第三方库时。如果您搜索 React + d3,您会发现几种处理方法。
    • 例外?你的意思是应该避免改变 dom 的一般规则有例外?
    • 是的。显然,如果你想使用一个不是 React 的组件,你必须想办法让它工作。但是您自己不应该手动执行任何 DOM 突变。这是我集成 CodeMirror 的示例(公平地说,这很简单):github.com/fkling/exerslide/blob/master/components/Editor.js
    • @BrainLikeADullPencil @Felix 你不应该改变 由 React 管理的 DOM。在你渲染 React 的元素之外改变 DOM 是完全可以接受的。如果您不得不使用像d3这样的库inside组件,可以将元素附加到inside组件中,只要每次状态更改时,您也以完全相同的方式应用附加。否则你的追加将被覆盖,当 React 重新渲染组件时你会看到不一致。另外,请记住,如果您操作托管 DOM,React 可能经常会重新渲染而无用
    【解决方案2】:

    避免在 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,而是另一个具有附加方法的库。 (我认为您的解决方案仍然适用)。我刚刚使用 jquery 来解决这个问题,因为它说明了问题并且很容易在 jsfiddle 上设置。我会尝试你的答案并稍后接受
    【解决方案3】:

    这是您的 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 的库?不合适吗?
    • 我不知道。我使用过 d3.js,但没有使用 React。你可以操纵 DOM,你不应该把它作为你的 React 组件的一部分来做
    猜你喜欢
    • 1970-01-01
    • 2012-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-25
    • 2017-07-16
    • 2019-05-24
    • 2016-04-19
    相关资源
    最近更新 更多