资讯专栏INFORMATION COLUMN

React as a UI Runtime(四、条件)

stonezhu / 3049人阅读

摘要:我们不想要因为重新创建元素而失去它的选中状态,聚焦状态和显示内容。幸好这个问题有一个简单的修复方式,他并不在应用中常见。那么会执行类似于下面的代码的状态并不会改变

如果React在更新中只重用与元素类型相匹配的宿主实例,那按渲染条件选择的内容怎么办呢?
正如下面的代码,假如我们开始至需要一个input,但稍后需要在它之前渲染一个message
// 第一次渲染
ReactDOM.render(
  
    
  ,
  domContainer
);

// 第二次渲染
ReactDOM.render(
  
    

I was just added here!

, domContainer );

在这个例子中,宿主实例将会被重建。React会遍历元素树,并与之前的版本比较:

dialog → dialog: 可以重复使用吗? 可以-type匹配。

input → p:可以重复使用吗?不行,type已经改变了!需要删除存在的input,并创建新的p宿主实例。

(nothing) → input: 需要新建一个input宿主实例。

React这样的代码是如下的:

let oldInputNode = dialogNode.firstChild;
dialogNode.removeChild(oldInputNode);

let pNode = document.createElement("p");
pNode.textContent = "I was just added here!";
dialogNode.appendChild(pNode);

let newInputNode = document.createElement("input");
dialogNode.appendChild(newInputNode);

这不是一种好的更新方式,因为原则上input并没有被p替代-它仅仅是移动了。我们不想要因为重新创建Dom元素而失去它的选中状态,聚焦状态和显示内容。
幸好这个问题有一个简单的修复方式,他并不在React应用中常见。
在实践中,你很少会直接调用ReactDOM.render,实际上,React app常常会拆分成像下面这样的函数:

function Form({ showMessage }) {
  let message = null;
  if (showMessage) {
    message = 

I was just added here!

; } return ( {message} ); }

This example doesn’t suffer from the problem we just described. It might be easier to see why if we use object notation instead of JSX. Look at the dialog child element tree:
这个例子并不会有我们之前描述的那个问题,如果我们使用对象来代替JSX描述会更加明显,下面是dialog子元素树:

function Form({ showMessage }) {
  let message = null;
  if (showMessage) {
    message = {
      type: "p",
      props: { children: "I was just added here!" }
    };
  }
  return {
    type: "dialog",
    props: {
      children: [
        message,
        { type: "input", props: {} }
      ]
    }
  };
}

function Form({ showMessage }) {
let message = null;
if (showMessage) {

message = {
  type: "p",
  props: { children: "I was just added here!" }
};

}
return {

type: "dialog",
props: {
  children: [
    message,
    { type: "input", props: {} }
  ]
}

};
}

不管showMessage 是true的还是false,是第二个子元素,并且在render中不会改变它的位置。
如果showMessage 从false变为true,React会遍历元素树,并与之前的版本相比较:

dialog → dialog:可以重复使用吗? 可以-type匹配。

(null) → p:需要插入一个新的p宿主实例。

input → input: 可以重复使用吗? 可以-type匹配。

那么React会执行类似于下面的代码:

let inputNode = dialogNode.firstChild;
let pNode = document.createElement("p");
pNode.textContent = "I was just added here!";
dialogNode.insertBefore(pNode, inputNode);

input的状态并不会改变

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/101937.html

相关文章

  • React as a UI Runtime(二、React元素和入口)

    摘要:元素在宿主环境中,一个宿主实例是最小的单位像节点。在中最小的单位是元素。他们总是不断的重建和销毁。元素是不可变的。比如,你不能改变一个元素的属性和其他属性。入口每一个渲染器都有一个入口。当我们说,就意味着亲爱的,将我的元素放到的宿主树去。 1、React元素 在宿主环境中,一个宿主实例是最小的单位(像DOM节点)。在React中最小的单位是React元素。一个React元素就是一个描述...

    zhjx922 评论0 收藏0
  • React as a UI Runtime(三、协调)

    摘要:确定宿主树怎么样来响应新的信息的这个过程被称为协调。协调有两种方法。我们已经创建了一个作为第一个也是唯一一个子元素,并且我们希望在同一个地方再次渲染一个。这个已经与的思想非常接近了。 1.协调 如果我们在同一个容器中使用两次ReactDOM.render()会发生什么? ReactDOM.render( , document.getElementById(container) ...

    刘德刚 评论0 收藏0
  • React as a UI Runtime(五、列表)

    摘要:但是这只在子元素的位置是静止的并且不需要重排。这可能会引起性能问题和可能的。当在中发现,它就会检查之前版本中的是否同样含有。并没有惯用的支持对在不重新创建元素的情况下让宿主实例在不同的父元素之间移动。 通过比较树中的元素是否在同一位置,通常已经足够判断是否是重用还是再次创建通信组件了。但是这只在子元素的位置是静止的并且不需要重排。在我们的上述的例子中,即使message不存在,我们仍然...

    CoyPan 评论0 收藏0
  • React Native Vs. Xamarin Vs. Ionic Vs. Flutter

    React Native Vs. Xamarin Vs. Ionic Vs. Flutter:Which Is Best For Cross-Platform Mobile App Development? While developing Native Mobile Apps, Android apps are written in Java, and iOS ones in Swift and...

    Clect 评论0 收藏0

发表评论

0条评论

stonezhu

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<