试试这么读 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 方法。

原文地址

相关文章
相关标签/搜索