Skip to content

Fragment

Anshi edited this page Apr 19, 2019 · 1 revision

Fragment

fragment 是写 key 的前置条件吧,因为我发现 react 源码在针对数组的子元素时,会将其标记为一个 Fragment 类型的 fiber。

image-20190419115538305

如上图,针对 data 渲染出的数组元素,react 会使用一个 fragment fiber 包裹,渲染其子元素,也就是这个数组。

beginWork - 渲染 fragment

function updateFragmentComponent(wipFiber: Fiber): void {
  const newChildElements = wipFiber.pendingProps.children;
  reconcileChildrenArray(wipFiber, newChildElements);
}

fragmentComponent 的结构类似 hostComponent,在处理这样的 fiber 的 work 时没有额外的操作。

值得注意的是, fiber 节点里的 tag 和 type 两个属性,tag 属性是 fiber 自有的,在处理 work 时的标识符,常见的值如下:

image-20190419144303390

type 属性是继承自 element ,类型有function|class|string|symbol (这里类型分的不严谨),对于 Fragment 其 type 是一个 symbol 值。

export const REACT_FRAGMENT_TYPE = Symbol.for('react.fragment')

所以在渲染 fragment 元素时,需要一个 type => tag 的映射。

Reconcile - 渲染 fragment 子元素

    case 'symbol':
      if (ele.type === REACT_FRAGMENT_TYPE) {
        tag = Fragment;
      }
      /* ele.type 的typeof 怎么是 symbol + function */
      break;

非主动使用 fragment

除了主动在 jsx 中引入 fragment 元素外,react 还会在处理数组元素时,默认用一个 fragment 包裹,一如文章开头所述,我想这就是react 在16 后支持 return 一个数组的原因吧。

  if (Array.isArray(ele)) {
    ele = {
      type: REACT_FRAGMENT_TYPE,
      props: { children: [...ele] },
      key: ele.key
    };
  }

其他 babel 配置

  "plugins": [
    ["@babel/plugin-transform-react-jsx", { "pragma":"createElement","pragmaFrag":"Fragment" }]
  ]

由于在调试时想使用 jsx 语法编写,所以引用了plugin-transform-react-jsx,配置如下(其实不配置也可以,因为我们的命名和导出规则都参照的 react)。

Clone this wiki locally