React (虛擬)DOM 術(shù)語

2019-08-14 14:29 更新

在 React 的術(shù)語中,有五個核心類型,區(qū)分它們是很重要的:

React 元素

React 中最主要的類型就是 ReactElement。它有四個屬性:type,propskey  ref。它沒有方法,并且原型上什么都沒有。

可以通過 React.createElement 創(chuàng)建該類型的一個實例。

var root = React.createElement('div');

為了渲染一個新的樹形結(jié)構(gòu)到 DOM 中,你創(chuàng)建若干個 ReactElement,然后傳給 React.render 作為第一個參數(shù),同時將第二個參數(shù)設(shè)為一個正規(guī)的 DOM 元素 (HTMLElement 或者 SVGElement)。不要混淆 ReactElement 實例和 DOM元素 實例。一個 ReactElement 實例是一個輕量的,無狀態(tài)的,不可變的,虛擬的 DOM 元素 的表示。是一個虛擬 DOM。

React.render(root, document.body);

要添加屬性到 DOM 元素,把屬性對象作為第二個參數(shù)傳入 React.render,把子級作為第三個參數(shù)傳給React.render。

var child = React.createElement('li', null, 'Text Content');var root = React.createElement('ul', { className: 'my-list' }, child);
React.render(root, document.body);

如果使用 React JSX 語法,這些 ReactElement 實例自動創(chuàng)建。所以,如下代碼是等價的:

var root = <ul className="my-list">
             <li>Text Content</li>
           </ul>;
React.render(root, document.body);

工廠

一個 ReactElement 工廠就是一個簡單的函數(shù),該函數(shù)生成一個帶有特殊 type 屬性的 ReactElement。React 有一個內(nèi)置的輔助方法用于創(chuàng)建工廠函數(shù)。事實上該方法就是這樣的:

function createFactory(type){  return React.createElement.bind(null, type);
}

該函數(shù)能創(chuàng)建一個方便的短函數(shù),而不是總調(diào)用 React.createElement('div')。

var div = React.createFactory('div');var root = div({ className: 'my-div' });
React.render(root, document.body);

React 已經(jīng)內(nèi)置了常用 HTML 標(biāo)簽的工廠函數(shù):

var root = React.DOM.ul({ className: 'my-list' },
             React.DOM.li(null, 'Text Content')
           );

如果使用 JSX 語法,就不需要工廠函數(shù)了。JSX 已經(jīng)提供了一種方便的短函數(shù)來創(chuàng)建 ReactElement 實例。

React 節(jié)點

一個 ReactNode 可以是:

  • ReactElement

  • string (又名 ReactText

  • number (又名 ReactText

  • ReactNode 實例數(shù)組 (又名 ReactFragment

這些被用作其它 ReactElement 實例的屬性,用于表示子級。實際上它們創(chuàng)建了一個 ReactElement 實例樹。 (These are used as properties of other ReactElements to represent children. Effectively they create a tree ofReactElements.)

React 組件

在使用 React 開發(fā)中,可以僅使用 ReactElement 實例,但是,要充分利用 React,就要使用 ReactComponent 來封裝狀態(tài)化的組件。

一個 ReactComponent 類就是一個簡單的 JavaScript 類(或者說是“構(gòu)造函數(shù)”)。

var MyComponent = React.createClass({
  render: function() {
    ...
  }
});

當(dāng)該構(gòu)造函數(shù)調(diào)用的時候,應(yīng)該會返回一個對象,該對象至少帶有一個 render 方法。該對象指向一個 ReactComponent實例。

var component = new MyComponent(props); // never do this

除非為了測試,正常情況下不要自己調(diào)用該構(gòu)造函數(shù)。React 幫你調(diào)用這個函數(shù)。

相反,把 ReactComponent 類傳給 createElement,就會得到一個 ReactElement 實例。

var element = React.createElement(MyComponent);

或者使用 JSX:

var element = <MyComponent />;

當(dāng)該實例傳給 React.render 的時候,React 將會調(diào)用構(gòu)造函數(shù),然后創(chuàng)建并返回一個 ReactComponent。

var component = React.render(element, document.body);

如果一直用相同的 ReactElement 類型和相同的 DOM 元素容器調(diào)用 React.render,將會總是返回相同的實例。該實例是狀態(tài)化的。

var componentA = React.render(<MyComponent />, document.body);var componentB = React.render(<MyComponent />, document.body);
componentA === componentB; // true

這就是為什么不應(yīng)該創(chuàng)建你自己的實例。相反,在創(chuàng)建之前,ReactElement 是一個虛擬的 ReactComponent。新舊ReactElement 可以比對,從而決定是創(chuàng)建一個新的 ReactComponent 實例還是重用已有的實例。

ReactComponent 的 render 方法應(yīng)該返回另一個 ReactElement,這就允許組件被組裝。 (The render method of a ReactComponent is expected to return another ReactElement. This allows these components to be composed. Ultimately the render resolves into ReactElement with a string tag which instantiates a DOMElement instance and inserts it into the document.)

正式的類型定義

入口點(Entry Point)

React.render = (ReactElement, HTMLElement | SVGElement) => ReactComponent;

節(jié)點和元素(Nodes and Elements)

type ReactNode = ReactElement | ReactFragment | ReactText;

type ReactElement = ReactComponentElement | ReactDOMElement;

type ReactDOMElement = {
  type : string,
  props : {
    children : ReactNodeList,
    className : string,
    etc.
  },
  key : string | boolean | number | null,  ref : string | null};

type ReactComponentElement<TProps> = {
  type : ReactClass<TProps>,
  props : TProps,
  key : string | boolean | number | null,  ref : string | null};

type ReactFragment = Array<ReactNode | ReactEmpty>;

type ReactNodeList = ReactNode | ReactEmpty;

type ReactText = string | number;

type ReactEmpty = null | undefined | boolean;

類和組件(Classes and Components)

type ReactClass<TProps> = (TProps) => ReactComponent<TProps>;

type ReactComponent<TProps> = {
  props : TProps,
  render : () => ReactElement
};


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號