試試這麼讀 preact 源碼(二)- render

舊版本中的 render 方法只作了一件事,就是調起 diff 方法,新版本中的 render 引入了 Fragment ,讓咱們寫的自定義組件都成了子組件node

React.Fragment

Fragment 就是讓 react 組件可以聚合一個個子元素列表,那樣就沒必要要在增長一個額外的節點了react

// 舊的寫法
render(){
    return (
        <div> <ChildA /> <ChildB /> <ChildC /> </div>
    )
}

// Fragment
render(){
    return (
        <> <ChildA /> <ChildB /> <ChildC /> </> ) } 複製代碼

<></> 實際上是 <React.Fragment/> 的語法糖,當組件中須要遍歷數組傳遞 key 值時,就須要使用 <React.Fragment/>git

render(){
    return (
        <div> { goodsList.map(item => ( <React.Fragment key={item.id}> <p>{item.goodsName}</p> </React.Fragment> )) } </div> ) } 複製代碼

瞭解了 reactFragment ,那 preact 是如何使用和實現的呢:github

使用:api

import {h, render, Component, Fragment} from 'preact';

class App extends Component {
    render(){
        return (
            <Fragment> <div>preact</div> <div>使用了Fragment</div> </Fragment>
        )
    }
}

複製代碼

preact 中,並無相似 <></> 這樣的語法糖,下面來看下它的實現原理:數組

function Fragment() {}

function render(vnode, parentDom, replaceNode) {
    // ...
    vnode = createElement(Fragment, null, [vnode]);
    // ...
}
複製代碼

render 方法中調用了 createElement 方法建立了一個虛擬 dom ,第一個參數就是 Fragment ,實參是一個 functioncreateElement 這個函數的第一個形參 type 是這個虛擬 dom 的類型,它有多是 div,span 等,也有多是一個 function,當講到 diff 時,會專門有一個分支就是判斷 type === Fragment 的狀況,那個時候再細講,這裏只簡單說下結果:dom

Fragment 做爲虛擬dom的類型傳入,在diff 一個組件時,時若是遇到 type === Fragment 時,就直接 diff <Fragment></Fragment> 包裹的子節點,而這些子節點所渲染的真實 dom 會直接掛載在 <Fragment></Fragment> 所對應的父節點上。函數

以上就是 Fragment 的簡單實現,在 render 方法中,經過 createElement 方法從新建立的 vnode 會傳入 diffChildren 方法中,這個方法是整個新版中最核心的方法,將在後面專門會說這個方法,這裏能夠簡單的理解爲--對比這個 vnode 下的子節點是否更新。spa

在這個 render 方法中,因爲最外層包裹的是一個 Fragment ,因此,這裏的 diffChildren 比對的對象就是 Fragment 包裹下的子節點。code

下一章,咱們就來看看這個 diffChildren 方法。

原文地址

相關文章
相關標籤/搜索