React as a UI Runtime(四、条件)

栏目: 服务器 · 发布时间: 6年前

内容简介:如果React在更新中只重用与元素类型相匹配的宿主实例,那按渲染条件选择的内容怎么办呢?正如下面的代码,假如我们开始至需要一个在这个例子中,

如果React在更新中只重用与元素类型相匹配的宿主实例,那按渲染条件选择的内容怎么办呢?

正如下面的代码,假如我们开始至需要一个 input ,但稍后需要在它之前渲染一个 message

// 第一次渲染
ReactDOM.render(
  <dialog>
    <input />
  </dialog>,
  domContainer
);

// 第二次渲染
ReactDOM.render(
  <dialog>
    <p>I was just added here!</p>
    <input />
  </dialog>,
  domContainer
);

在这个例子中, <input> 宿主实例将会被重建。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 = <p>I was just added here!</p>;
  }
  return (
    <dialog>
      {message}
      <input />
    </dialog>
  );
}

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, <input> 是第二个子元素,并且在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的状态并不会改变


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

与机器赛跑

与机器赛跑

[美]埃里克·布林约尔松(Erik Brynjolfsson)、[美]安德鲁·麦卡菲(Andrew McAfee) / 闾佳 / 2013-1-20 / 6.00

一场数字革命正在加速进行。 一些科幻小说里的场景已经在现实中发生:无人驾驶汽车开上了公路;智能设备能高效地翻译人类语言;人工智能系统在智力竞赛里击败了所有人类选手;工厂雇主开始购买更多的新机器,却不招新工人…… 这些例子都证明,数字技术正在快速地掌握原本只属于人类的技能,并深刻地影响了经济。虽然大多数影响是积极的:数字革新将提高效率、降低商品价格(甚至到免费),以及增加经济总量。 ......一起来看看 《与机器赛跑》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

在线进制转换器
在线进制转换器

各进制数互转换器

html转js在线工具
html转js在线工具

html转js在线工具