简体   繁体   English

如何在React中处理第三方dom操纵?

[英]How to handle third-party dom manipulation in React?

I am new to React and not sure what is the proper way of dealing with the following situation: 我是React的新手,不确定如何处理以下情况:

I made a component that renders code and uses Highlight.js to highlight the syntax. 我制作了一个呈现代码并使用Highlight.js突出显示语法的组件。
It worked, but broke when the content updated. 它有效,但是在内容更新时中断了。

class CodeBox extends React.Component {
    componentDidMount() {
        this.highlight();
    }
    componentDidUpdate() {
        this.highlight();
    }
    highlight() {
        hljs.highlightBlock(this.elem);
    }
    render() {
        return (
            <pre><code ref={(elem) => { this.elem = elem }}>{this.props.code}</code></pre>
        );
    }
}

My understanding is that React handles the code node, and doesn't like when Highlight.js tampers with it... so i resorted to this: 我的理解是React处理code节点,并且不喜欢Highlight.js对其进行篡改...所以我诉诸于此:

class CodeBox extends React.Component {
    componentDidMount() {
        this.highlight();
    }
    componentDidUpdate() {
        this.highlight();
    }
    highlight() {
        this.elem.innerHTML = "";
        let c = document.createElement("code");
        c.innerHTML = this.props.code;
        this.elem.appendChild(c);
        hljs.highlightBlock(c);
    }
    render() {
        return (
            <pre ref={(elem) => { this.elem = elem }}></pre>
        );
    }
}

Which works, but now i feel like i'm using React wrong. 哪个可行,但现在我感觉我使用React错误。
Is there a way to do this that doesn't involve directly manipulating the dom ? 有没有办法不涉及直接操纵dom的方法呢?

You can use dangerouslySetInnerHTML to achieve the same result without using refs or altering the DOM after rendering, however because of how Highlight.js works, you still have to use a fake HTML element. 您可以使用dangerouslySetInnerHTML地设置内部HTML来获得相同的结果,而无需在渲染后使用引用或更改DOM,但是由于Highlight.js工作方式,您仍然必须使用伪造的HTML元素。

To do this, instead of using the componentDidUpdate and componentDidMount methods we can use the componentWillMount and componentWillReceiveProps methods like so: 要做到这一点,而不是使用componentDidUpdatecomponentDidMount方法,我们可以使用componentWillMountcomponentWillReceiveProps方法如下所示:

componentWillMount() {
    this.highlight(this.props);
}
componentWillReceiveProps(newProps) {
    this.highlight(newProps);
}
highlight(props) {        
    parseElement.innerHTML = props.code;        
    hljs.highlightBlock(parseElement);
    this.setState({
        code: {__html: parseElement.innerHTML}
    });
}

and then we render out the new already formatted code in the render method: 然后在render方法中渲染出新的已经格式化的代码:

return (
   <pre><code dangerouslySetInnerHTML={this.state.code} /></pre>
);

Here is a JS Fiddle 这是一个JS小提琴

this is still not ideal, but it doesn't break React principles, while still using Highlight.js that relies on additional DOM manipulations. 这仍然不是理想的,但是它没有违反React原则,同时仍然使用Highlight.js依赖其他DOM操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM