旧版本中的 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>
)
}
了解了 react
的 Fragment
,那 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
,实参是一个 function
。createElement
这个函数的第一个形参 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
方法。
网友评论