【问题标题】:Updating the Rendered Element(immutable)更新渲染元素(不可变)
【发布时间】:2019-02-26 20:02:31
【问题描述】:

React tutorial ,上面写着

React 元素是不可变的。一旦你创建了一个元素,你就不能改变它的子元素或属性。元素就像电影中的单个帧:它代表某个时间点的 UI。 根据我们目前的知识,更新 UI 的唯一方法是创建一个新元素并将其传递给 ReactDOM.render()。

在下一个标题中,它说

React 只更新什么是必要的

React DOM 将元素及其子元素与前一个元素进行比较,并且仅应用必要的 DOM 更新以使 DOM 达到所需状态。

他们的例子-

function tick() {
  const element = (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {new Date().toLocaleTimeString()}.</h2>
    </div>
  );
  ReactDOM.render(element, document.getElementById('root'));
}

setInterval(tick, 1000);

在这个例子中,React 只更新时间 - &lt;h2&gt;It is {new Date().toLocaleTimeString()}.&lt;/h2> 代码行。因为这只是必要的更改,但我无法理解 React 如何更改 Immutable 对象,因为他们提到了

React 元素是不可变的。创建元素后,您无法更改其子元素或属性。

因此,与其只更改“Just Time Part”(上述代码示例),还应更改整个 React 元素。 我无法理解 React 如何在 Immutable 对象内进行必要的更新(在上面的情况下它是元素)或者我错过了什么?

【问题讨论】:

  • 元素确实是不可变的。 React 并没有改变它,它把所有的东西都扔掉了,制作了一个全新的版本。 (element 仅在 tick 函数的范围内,一旦它运行,每秒,element 将被垃圾收集)。当然这是非常低效的,所以如果你继续阅读文档,你会看到它继续到 React “组件”,它们是可变的,并且会自动选择性地更新自己以响应某些触发器。据我所知,“现实世界”的 React 应用程序只使用组件,而不是“元素”。
  • @RobinZigmond “全新版本”是什么意思?新版本是否仅表示包含时间的行(

    它是 {new Date().toLocaleTimeString()})。是的,我认为这是真的——“元素”将被垃圾收集。不,我还没有通过组件,我会阅读。

  • @JoshiYogesh - 我现在真的很困惑,哈哈。 (不久前我自学了 React,我几乎不是专家或任何东西。)我实际上的意思是整个元素被“扔掉”(垃圾收集”,并制作了一个新元素 - 我'就element,JS对象而言,我仍然很确定这是正确的。但是经过更多思考(包括阅读下面的答案)我确实认为React只会在更新DOM本身时改变最小的必要部分。从 JS 的角度来看,这并没有改变元素是不可变的事实。

标签: javascript reactjs


【解决方案1】:

它不会对 React 元素树(“不可变对象”)进行更新。它将先前的树与当前的树进行比较,并对 DOM 进行必要的更新。

React Element Tree 是 DOM 的一种简化形式。这就像一个快照。 React 拥有当前的快照,当应用程序的状态发生变化时,它会创建一个新状态来反映 DOM 的外观。 React 比较这两个快照并对 DOM 进行必要的更改,以便它镜像新的快照。之后,旧的、过时的快照被丢弃,新的快照成为 DOM 的当前快照。

基本上,你有:

  • 应用的状态
  • 描述应用在给定状态下的外观(您编写的 React 代码)
  • 快照(React 元素树)
  • 区分和更新机器(React 库)
  • DOM

DOM 或外部世界(即服务器)产生改变状态的事件。根据描述为该状态创建一个新快照。比较新旧快照并将更改引入 DOM。这个过程一遍又一遍地重复。

您可以在这篇精彩的博文中查看并了解有关 React 元素的更多信息:https://reactjs.org/blog/2015/12/18/react-components-elements-and-instances.html

【讨论】:

    【解决方案2】:

    React 组件在内部使用 createElement 构建:

    React.createElement(type, props)
    

    因此,当对其道具应用任何更改时,值会更新,但不会更新其类型。

    例如:

    React.createElement('h1', 'Hello, world!')
    // first param is type, and second is prop
    

    这里的prop没有改变,因此这个元素不会被更新。


    组件可以用 createElement 来编写,例如:

    React.createElement('div',
       React.createElement('h1', 'Hello world!'),
       React.createElement(....),
       React.createElement(...)
    )
    

    因此,每当特定元素的任何道具发生变化时,该元素只会被更新。

    为什么只更新道具,而不是输入ie。元素?

    这是因为 React 将它们存储在 ReactDOM 对象中而不是 HTML DOM 中。它会仔细分析需要更新的内容。 ReactDOM 只是一个具有键值对的对象。

    例如,React 初始化它的 dom 如下:

    var ReactDOM = {}
    

    现在,无论属性需要更新,都可以处理。

    Object.defineProperties(ReactDOM, {
      type: { // creating immutable property
        value: 'h1',
        writable: false,
        configurable: false
      },
      props: {
        writable: true,
        value: 'MY PROPS'
      }
    });
    Object.seal(ReactDOM)
    

    现在,props 可以更改,但type 不能更改。

    ReactDOM.props = 'will be updated'
    ReactDOM.type = 'will not be updated'
    console.log(ReactDOM.type) // 'h1'
    console.log(ReactDOM.props) // 'will be updated'
    

    我希望这可以澄清 React 的元素是不可变的。

    【讨论】:

    • 好的 .. 理解 bcz 它的值是以 Key | 的形式存储的。 React DOM 中的值对,这就是它发生这种情况的原因。但是无法理解一个事实......当 setInterval(trick,1000) 执行时,react DOM 应该在间隔内连续分配给 HTML DOM。但在 Web 控制台中,它每次只显示
    • reactjs.org/… 在这你不认为所有的
      都应该更新吗?
    • @JoshiYogesh 否。仅更新时间值。我已经回答得很清楚了。我不是吗?
    • 好的。现在知道了
    • 好。你明白了。
    猜你喜欢
    相关资源
    最近更新 更多
    热门标签