Skip to content

处理边界情况 ​

本节目标:理解“处理边界情况”的核心思路,并能把它用于实际开发或面试表达。

文本的处理, 需要自己增加类型。因为不能通过document.createElement('文本')
h(
  'h1',
  {
    style: { color: 'red' },
    onClick: () => alert(1)
  },
  [
    h('span', '123'),
    '123'
  ]
)
vnode.ts添加一个类型标识Text
import { isArray, isString, ShapeFlags } from "@vue/shared";
export const Text = Symbol('Text')
这样的话,
let shapeFlag = isString(type) ? ShapeFlags.ELEMENT : 0;
得到shapeFlag为0;之后
if (children) {
  let type = 0;
  if (isArray(children)) {
    type = ShapeFlags.ARRAY_CHILDREN;
  } else {
    children = String(children);
    type = ShapeFlags.TEXT_CHILDREN;
  }
  vnode.shapeFlag |= type
}
这里的最终结果是vnode.shapFlag的值为ShapeFlags.ARRAY_CHILDREN或者ShapeFlags.TEXT_CHILDREN,就像没有赋予权限一样的
接下来,在renderer.ts的patch方法中,添加一个逻辑:
const patch = (n1, n2, container) => {
  if (n1 === n2) return;
  const { type, shapeFlag } = n2
  switch (type) {
    case Text:
      processText(n1, n2, container);
      break;
    default:
      if (shapeFlag & ShapeFlags.ELEMENT) {
        processElement(n1, n2, container);
      }
  }
}
const processText = (n1, n2, container) => {
  if (n1 === null) {
    hostInsert((n2.el = hostCreateText(n2.children)), container)
  } else {
    // 文本的内容变化了,我可以复用老的节点
    const el = n2.el = n1.el;
    if (n1.children !== n2.children) {
      hostSetText(el, n2.children); // 文本的更新
    }
  }
}
在mountChildren中,还要进行处理:
const mountChildren = (children, container) => {
  for (let i = 0; i < children.length; i++) {
    let child = normalize(children[i])
    patch(null, child, container)
  }
}
const normalize = (child) => {
  if (isString(child)) {
    return createVnode(Text, null, child)
  }
  return child
}

本站总访问 — 次