美文网首页Web前端之路前端开发
试试这么读preact源码(二)- render

试试这么读preact源码(二)- render

作者: 爱甩尾巴的猫 | 来源:发表于2019-05-16 10:01 被阅读1次

    旧版本中的 render 方法只做了一件事,就是调起 diff 方法,新版本中的 render 引入了 Fragment ,让我们写的自定义组件都成了子组件

    React.Fragment

    Fragment 就是让 react 组件能够聚合一个个子元素列表,那样就不必要在增加一个额外的节点了

    // 旧的写法
    render(){
        return (
            <div>
              <ChildA />
              <ChildB />
              <ChildC />
            </div>
        )
    }
    
    // Fragment
    render(){
        return (
            <>
              <ChildA />
              <ChildB />
              <ChildC />
            </>
        )
    }
    
    

    <></> 其实是 <React.Fragment/> 的语法糖,当组件中需要遍历数组传递 key 值时,就需要使用 <React.Fragment/>

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

    了解了 reactFragment ,那 preact 是如何使用和实现的呢:

    使用:

    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 的情况,那个时候再细讲,这里只简单说下结果:

    Fragment 作为虚拟dom的类型传入,在diff 一个组件时,时如果遇到 type === Fragment 时,就直接 diff <Fragment></Fragment> 包裹的子节点,而这些子节点所渲染的真实 dom 会直接挂载在 <Fragment></Fragment> 所对应的父节点上。

    以上就是 Fragment 的简单实现,在 render 方法中,通过 createElement 方法重新创建的 vnode 会传入 diffChildren 方法中,这个方法是整个新版中最核心的方法,将在后面专门会说这个方法,这里可以简单的理解为--对比这个 vnode 下的子节点是否更新。

    在这个 render 方法中,由于最外层包裹的是一个 Fragment ,所以,这里的 diffChildren 比对的对象就是 Fragment 包裹下的子节点。

    下一章,我们就来看看这个 diffChildren 方法。

    原文地址

    相关文章

      网友评论

        本文标题:试试这么读preact源码(二)- render

        本文链接:https://www.haomeiwen.com/subject/iwjbaqtx.html