React as a UI Runtime(4、條件)

若是React在更新中只重用與元素類型相匹配的宿主實例,那按渲染條件選擇的內容怎麼辦呢?
正以下面的代碼,假如咱們開始至須要一個 input,但稍後須要在它以前渲染一個 message
// 第一次渲染
ReactDOM.render(
  <dialog>
    <input />
  </dialog>,
  domContainer
);

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

在這個例子中,<input>宿主實例將會被重建。React會遍歷元素樹,並與以前的版本比較:app

  • dialog → dialog: 能夠重複使用嗎? 能夠-type匹配。
  • input → p:能夠重複使用嗎?不行,type已經改變了!須要刪除存在的input,並建立新的p宿主實例。
  • (nothing) → input: 須要新建一個input宿主實例。

React這樣的代碼是以下的:dom

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子元素樹:code

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) {orm

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

}
return {對象

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

};
}element

無論showMessage 是true的仍是false,<input>是第二個子元素,而且在render中不會改變它的位置。
若是showMessage 從false變爲true,React會遍歷元素樹,並與以前的版本相比較:rem

  • dialog → dialog:能夠重複使用嗎? 能夠-type匹配。
  • (null) → p:須要插入一個新的p宿主實例。
  • input → input: 能夠重複使用嗎? 能夠-type匹配。

那麼React會執行相似於下面的代碼:input

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

input的狀態並不會改變io

相關文章
相關標籤/搜索