在react中操作 DOM

IT技术 javascript reactjs
2021-05-01 02:25:11

我知道在 React 中直接操作 DOM 并不是一个好的做法。由于在比较虚拟 DOM 和真实 DOM 时,react 协调引擎会影响性能

但是如果我做这样的事情呢?

显示的场景仅用于解释问题。对于这种特定情况不需要答案,但这种做法一般都有缺点

场景:1

state = {
   innerHTML : ""
}

document.getElementById("test").innerHTML = this.state.innerHTML

handleChange(){
  //...handles change in state
}

场景:2

state = {
    color:"red"
}

document.getElementById("test").style.color = this.state.color

handleChange(color){
    this.setState({color})
}

在这种情况下,react 意识到它需要重新渲染,因为我正在更改状态,从而保持 Virtual DOM 和 Real DOM 的一致性

那么在所有这些我可以使用状态来保持一致性并对真实 DOM 进行更改的情况下,以这种方式对真实 DOM 进行更改仍然是一个坏主意吗?

2个回答

在这种情况下,而不是innerHTML直接设置,您应该使用dangerouslySetInnerHTML

class Component extends React.Component {
  state = {
    innerHTML: '',
  }

  handleChange() {
    this.setState({ innerHTML: '...' });
  }

  render() {
    return <div dangerouslySetInnerHTML={ { __html: this.state.innerHTML } }></div>;
  }
}

如文档中所述:

危险地SetInnerHTML

dangerouslySetInnerHTML是 ReactinnerHTML在浏览器 DOM 中使用的替代品一般来说,从代码中设置 HTML 是有风险的,因为很容易在不经意间将用户暴露给跨站点脚本 (XSS) 攻击。所以,你可以直接从 React 设置 HTML,但是你必须输入dangerouslySetInnerHTML并传递一个带有__html的对象,以提醒自己这是危险的。

此外,当使用 时dangerouslySetInnerHTML,React 将在区分虚拟 DOM 和真实 DOM(协调时忽略 DOM 的那部分,因此它的性能更高,因为它需要做的工作更少。

无论如何,如果你这样做:

document.getElementById('test').innerHTML = this.state.innerHTML;

在您的代码中的某个点,可能在componentDidUpdate(),然后render()再次调用(当您更新状态或父组件重新呈现时),您的更改将被覆盖,因此您需要不断更新它,这可能会产生小而明显的闪存并降低性能,因为每次渲染都必须更新 DOM 2 次(一次来自 React,另一次来自innerHTML)。

您可以考虑使用 ReactRef 而不是必须直接操作 DOM,它更容易、更安全和更佳实践。

在这里检查