react element是「React.createElement」函數的返回值,即ReactElement;ReactElement的結構是「const element = {Element $$typeof: REACT_ELEMENT_TYPE,key: key,ref: ref,props: props,_owner: owner, };」。
本教學操作環境:Windows10系統、react16.9.0版、Dell G3電腦。
react element什麼意思?
React原始碼 | ReactElement
說到ReactElement,不得不提到的就是在React中,用來替代JavaScript(JS)的語言,JSX。
作為React的官方指定語法,JSX允許使用者在JS程式碼中插入HTML程式碼。但是,這種寫法瀏覽器是無法解析的。他們需要一個轉換器,Babel就充當了這樣一個角色,他在JSX程式碼編譯時候將其轉換成JS檔案,這樣瀏覽器就能解析了。
怎麼轉換呢,我們知道,JSX有JS和HTMl兩種寫法,本身就是JS寫法的其實是不需要轉換的,當然也不能說的這麼絕對,有時候Babel會為了相容性的緣故將高版本的語法翻譯到低版本,這部分不在討論範圍。我們要關注的其實是HTMl的處理方式。
比如下面這行程式碼:
<div id='name'>Tom and Jerry</div>
登入後複製
通過Babel轉換後生成的程式碼是:
React.createElement("div", {
id: "name"}, "Tom and Jerry");
登入後複製
HTML語法轉變成了JS語法,簡單來說,我們所寫的JSX最終變成了JS。
我們寫一個複雜點的例子:
<div class='wrapper' id='id_wrapper'>
<span>Tom</span>
<span>Jerry</span></div>React.createElement("div", {
class: "wrapper",
id: "id_wrapper"
}, React.createElement("span", null, "Tom"), React.createElement("span", null, "Jerry"));
登入後複製
轉換規則是比較簡單的,React.createElement的第一個引數是節點型別;第二個引數是該節點的屬性,以key:value的形式作為一個物件,後面的所有引數都是該節點的子節點。
需要注意的是,在JSX語法中,我們不僅有原生的HTML節點,還有大量的自定義元件,比如:
function Comp() {
return '<div>Tom and Jerry</div>'
}
<Comp></Comp>
function Comp() {
return '<div>Tom and Jerry</div>';
}
React.createElement(Comp, null);
登入後複製
可以看出,React.createElement的第一個引數變成了一個變數,而不是一個字串,嘗試將函數Comp首字母小寫:
function comp() {
return '<div>Tom and Jerry</div>'
}
<comp></comp>
function comp() {
return '<div>Tom and Jerry</div>';
}
React.createElement("comp", null);
登入後複製
React.createElement的第一個引數又變成了一個字串。
這也就是我們在React中寫元件的時候,為什麼會要求首字母大寫的原因,Babel在編譯的時候會將首字母小寫的元件視為原生的HTMl節點進行處理,如果我們將自定義元件首字母小寫,後續的程式將無法識別這個元件,最終會報錯。
通過Babel編譯後的JS程式碼,頻繁出現React.createElement這個函數。這個函數的返回值就是ReactElement,通過上面的範例可以看出,React.createElement函數的入參有三個,或者說三類。
type
type指代這個ReactElement的型別。
字串比如div,p代表原生DOM,稱為HostComponent
Class型別是我們繼承自Component或者PureComponent的元件,稱為ClassComponent
方法就是functional Component
原生提供的Fragment、AsyncMode等是Symbol,會被特殊處理
config
參照上面Babel編譯後的程式碼,所有節點的屬性都會以Key:Value的形式放到config物件中。
children
子節點不止會有一個,所以children不只有一個,從第二個引數以後的所有引數都是children,它是一個陣列。
ReactElement的結構是這樣的
const element = {
// This tag allows us to uniquely identify this as a React Element $$typeof: REACT_ELEMENT_TYPE,
// Built-in properties that belong on the element type: type,
key: key,
ref: ref,
props: props,
// Record the component responsible for creating this element. _owner: owner,
};
登入後複製
它就是一個簡單的物件,為了看清楚這個物件的建立規則,我們舉個例子。 首先是我們寫的JSX:
<div class='class_name' id='id_name' key='key_name' ref='ref_name'>
<span>Tom</span>
<span>Jerry</span>
</div>
登入後複製
它會被Babel編譯為:
React.createElement("div", {
class: "class_name",
id: "id_name",
key: "key_name",
ref: "ref_name"}, React.createElement("span", null, "Tom"), React.createElement("span", null, "Jerry"));
登入後複製
它會生成這樣一個Element
{
$$typeof: REACT_ELEMENT_TYPE,
type:'div',
key: 'key_name',
ref: "ref_name",
props: {
class: "class_name",
id: "id_name",
children: [
React.createElement("span", null, "Tom"),
React.createElement("span", null, "Jerry")
]
}
_owner: ReactCurrentOwner.current,}
登入後複製
$$typeof 是一個常數,所有通過React.createElement生成的元素都有這個值。一般使用 React 的元件都是掛到父元件的 this.props.children 上面,但是也有例外,比如要實現一個模態框,就需要將模態框掛載到body節點下,這個時候需要使用ReactDOM.createPortals(child, container)這個函數實現,這個函數生成的$$typeof值就是REACT_PORTAL_TYPE。
type指代這個ReactElement的型別
key和ref都是從config物件中找到的特殊設定,將其單獨抽取出來,放在ReactElement下
props包含了兩部分,第一部分是去除了key和ref的config,第二部分是children陣列,陣列的成員也是通過React.createElement生成的物件,範例中省略了這個步驟。
_owner在16.7的版本上是Fiber,Fiber是react16+版本的核心,暫時不做深究。
通過這篇文章,我們瞭解到,JSX中的HTML節點,在Babel的幫助下,轉換為巢狀的ReactElement物件,這些資訊對於後期構建應用的樹結構時非常重要的,而React通過提供這些型別的資料,來脫離平臺的限制。
推薦學習:《》
以上就是react element什麼意思的詳細內容,更多請關注TW511.COM其它相關文章!