javascript - 了解以下情况下的不变性和虚拟 DOM

标签 javascript reactjs immutability virtual-dom

阅读后here关于不变性,我试图了解 react 是如何工作的。我试图借助以下 3 个组件来理解,但它没有意义。

const bla = {a: 1};
class Test extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      a: 1,
    };
    this.onClick = () => this.setState(prevState => ({
      a: prevState.a + 1
    }));
  }
  render() {
    console.log('Render default');
    return <div id="test" onClick = {
      this.onClick
    } > DOM Updating: {
      this.state.a
    } < /div>;
  }
}

class Test1 extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      a: 1,
    };
    this.onClick = () => this.setState(prevState => ({
      a: 1
    }));
  }
  render() {
    console.log('Render 1');
    return <div id="test1" onClick = {
      this.onClick
    } > DOM not updating: {
      this.state.a
    } < /div>;
  }
}

class Test2 extends React.Component {
  constructor(props) {
    super(props);
    this.state = bla;
    this.onClick = () => {
      const mutating = this.state;
      mutating.a = this.state.a + 1;
      this.setState(mutating);
    };
  }
  render() {
    console.log('Render 2');
    return <div id="test2" onClick = {
      this.onClick
    } > DOM updating with mutation: {
      this.state.a
    } < /div>;
  }
}
ReactDOM.render( < div > < Test / > < Test1 / > < Test2 / > < /div>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

如果我检查 div id="test1",它会在每次点击时在 Chrome 开发工具中更新。想了解以下几点:

  1. 在点击期间如果我检查 div id="text1"为什么这没有反射(reflect)在开发工具中?在这里,我在每次点击时分配新的对象状态 ({a: 1})。正如上面的链接所说

In fact, React.js does not need to have knowledge about what exactly changed. All it needs to know is whether the state changed at all or not.

  • 在 Test2 组件中,我正在改变状态,但是为什么 dom 在点击时会更新?
  • 如果 updating nested state由于我们正在更新父状态,这是否意味着 React 会认为所有其他子项都已更改其值,并且即使它们没有更改,也会重新渲染所有值?
  • 最佳答案

    1.) 在控制台输出中,您只看到 Render 1,因为您使用静态值 1 调用 setState。但事实上,每次您通过单击调用 setState 时,React 都会为组件设置一个新的(在新对象引用的意义上)状态,并触发一个新的渲染周期。

    setState() will always lead to a re-render unless shouldComponentUpdate() returns false. Link

    2.) 请参阅答案 1。此外,您还更改了 DOM,因为 state changes are merged .

    When you call setState(), React merges the object you provide into the current state.

    在您的 Test2 点击处理程序代码中,变异将合并到当前状态。它是同一个对象,但重要的是,它的所有属性(此处为a属性)将被传播到状态中,从而产生一个新的状态对象。

    const mutating = this.state;
    mutating.a = this.state.a + 1;
    this.setState(mutating);
    

    3.) 假设您有一个包含所有子组件的 Parent 组件。如果您更改 Parentpropsstate,所有子项都将由 React 重新渲染,除非它们的 shouldComponentUpdate 钩子(Hook)返回false 或者它们是 PureComponent,其 props 或状态没有改变。

    setState() enqueues changes to the component state and tells React that this component and its children need to be re-rendered with the updated state. Link

    重新渲染意味着,对于每个子项,React 会在 Reconciliation 中比较先前版本和当前版本。步。如果子级确实发生了变化,它只会导致 DOM 更新,否则什么也不会发生。请参阅here以获得良好的可视化效果。

    关于javascript - 了解以下情况下的不变性和虚拟 DOM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57801985/

    相关文章:

    javascript - 如何使用node.js在server.js中传递参数

    javascript - Node.js 上的异步问题

    javascript - 如何使 jquery 模态始终位于页面中央?

    html - 在 JSON 字符串中 react i18n 换行

    javascript - 在没有 babel-polyfill 的情况下使用 async/await

    reactjs - React Native - 识别事件屏幕。抽屉导航器

    javascript - 如何在没有突变的情况下使用 javascript Map

    python - 在Python中操作不可变对象(immutable对象)时,新对象是如何创建的?

    javascript - JS 不可变对象(immutable对象)保持相同的对象类型

    javascript - 使用javascript向第一个 child 添加类(class)