{"id":31468,"date":"2024-11-25T13:15:07","date_gmt":"2024-11-25T05:15:07","guid":{"rendered":"https:\/\/fwq.ai\/blog\/31468\/"},"modified":"2024-11-25T13:15:07","modified_gmt":"2024-11-25T05:15:07","slug":"diff%e7%9a%84%e5%af%b9%e8%b1%a1%e6%98%af%e8%99%9a%e6%8b%9fdom","status":"publish","type":"post","link":"https:\/\/fwq.ai\/blog\/31468\/","title":{"rendered":"diff\u7684\u5bf9\u8c61\u662f\u865a\u62dfdom"},"content":{"rendered":"<p style=\"text-align: left\">\u8fd9\u6b21\u7ed9\u5927\u5bb6\u5e26\u6765diff\u7684\u5bf9\u8c61\u662f\u865a\u62dfdom\uff0c\u4f7f\u7528diff\u865a\u62df\u7684\u6709\u54ea\u4e9b\uff0c\u4e0b\u9762\u5c31\u662f\u5b9e\u6218\u6848\u4f8b\uff0c\u4e00\u8d77\u6765\u770b\u4e00\u4e0b\u3002<\/p>\n<p style=\"text-align: left\"><strong>\u865a\u62dfdom<\/strong><\/p>\n<p style=\"text-align: left\">diff\u7b97\u6cd5\u9996\u5148\u8981\u660e\u786e\u4e00\u4e2a\u6982\u5ff5\u5c31\u662fdiff\u7684\u5bf9\u8c61\u662f\u865a\u62dfdom\uff0c\u66f4\u65b0\u771f\u5b9edom\u5219\u662fdiff\u7b97\u6cd5\u7684\u7ed3\u679c<\/p>\n<p style=\"text-align: left\"><strong>Vnode\u57fa\u7c7b <\/strong><\/p>\n<pre> constructor (\r\n  \u3002\u3002\u3002\r\n ) {\r\n  this.tag = tag\r\n  this.data = data\r\n  this.children = children\r\n  this.text = text\r\n  this.elm = elm\r\n  this.ns = undefined\r\n  this.context = context\r\n  this.fnContext = undefined\r\n  this.fnOptions = undefined\r\n  this.fnScopeId = undefined\r\n  this.key = data &amp;&amp; data.key\r\n  this.componentOptions = componentOptions\r\n  this.componentInstance = undefined\r\n  this.parent = undefined\r\n  this.raw = false\r\n  this.isStatic = false\r\n  this.isRootInsert = true\r\n  this.isComment = false\r\n  this.isCloned = false\r\n  this.isOnce = false\r\n  this.asyncFactory = asyncFactory\r\n  this.asyncMeta = undefined\r\n  this.isAsyncPlaceholder = false\r\n }<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p style=\"text-align: left\">\u8fd9\u4e2a\u90e8\u5206\u7684\u4ee3\u7801 \u4e3b\u8981\u662f\u4e3a\u4e86\u66f4\u597d\u5730\u77e5\u9053\u5728diff\u7b97\u6cd5\u4e2d\u5177\u4f53diff\u7684\u7684\u542b\u4e49\uff0c\u5f53\u7136\u4e5f\u53ef\u4ee5\u66f4\u597d\u5730\u4e86\u89e3vnode\u5b9e\u4f8b<\/p>\n<p style=\"text-align: left\">\u6574\u4f53\u8fc7\u7a0b<\/p>\n<p style=\"text-align: left\"><strong>\u6838\u5fc3\u51fd\u6570\u662fpatch\u51fd\u6570<\/strong><\/p>\n<ul>\n<li>\n<p style=\"text-align: left\">isUndef\u5224\u65ad\uff08\u662f\u4e0d\u662fundefined\u6216\u8005null\uff09<\/p>\n<\/li>\n<li>\n<p style=\"text-align: left\">\/\/ empty mount (likely as component), create new root elementcreateElm(vnode, insertedVnodeQueue) \u8fd9\u91cc\u53ef\u4ee5\u53d1\u73b0\u521b\u5efa\u8282\u70b9\u4e0d\u662f\u4e00\u4e2a\u4e00\u4e2a\u63d2\u5165\uff0c\u800c\u662f\u653e\u5165\u4e00\u4e2a\u4e2d\u7edf\u4e00\u6279\u5904\u7406<\/p>\n<\/li>\n<li>\n<p style=\"text-align: left\">\u6838\u5fc3\u51fd\u6570sameVnode<\/p>\n<\/li>\n<\/ul>\n<pre>function sameVnode (a, b) {\r\n return (\r\n  a.key === b.key &amp;&amp; (\r\n   (\r\n    a.tag === b.tag &amp;&amp;\r\n    a.isComment === b.isComment &amp;&amp;\r\n    isDef(a.data) === isDef(b.data) &amp;&amp;\r\n    sameInputType(a, b)\r\n   ) || (\r\n    isTrue(a.isAsyncPlaceholder) &amp;&amp;\r\n    a.asyncFactory === b.asyncFactory &amp;&amp;\r\n    isUndef(b.asyncFactory.error)\r\n   )\r\n  )\r\n )\r\n}<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p style=\"text-align: left\">\u8fd9\u91cc\u662f\u4e00\u4e2a\u5916\u5c42\u7684\u6bd4\u8f83\u51fd\u6570\uff0c\u76f4\u63a5\u53bb\u6bd4\u8f83\u4e86\u4e24\u4e2a\u8282\u70b9\u7684key\uff0ctag\uff08\u6807\u7b7e\uff09,data\u7684\u6bd4\u8f83\uff08\u6ce8\u610f\u8fd9\u91cc\u7684data\u6307\u7684\u662fVNodeData\uff09\uff0cinput\u7684\u8bdd\u76f4\u63a5\u6bd4\u8f83type\u3002<\/p>\n<pre>export interface VNodeData {\r\n key?: string | number;\r\n slot?: string;\r\n scopedSlots?: { [key: string]: ScopedSlot };\r\n ref?: string;\r\n tag?: string;\r\n staticClass?: string;\r\n class?: any;\r\n staticStyle?: { [key: string]: any };\r\n style?: object[] | object;\r\n props?: { [key: string]: any };\r\n attrs?: { [key: string]: any };\r\n domProps?: { [key: string]: any };\r\n hook?: { [key: string]: Function };\r\n on?: { [key: string]: Function | Function[] };\r\n nativeOn?: { [key: string]: Function | Function[] };\r\n transition?: object;\r\n show?: boolean;\r\n inlineTemplate?: {\r\n  render: Function;\r\n  staticRenderFns: Function[];\r\n };\r\n directives?: VNodeDirective[];\r\n keepAlive?: boolean;\r\n}<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p style=\"text-align: left\">\u8fd9\u4f1a\u786e\u8ba4\u4e24\u4e2a\u8282\u70b9\u662f\u5426\u6709\u8fdb\u4e00\u6b65\u6bd4\u8f83\u7684\u4ef7\u503c\uff0c\u4e0d\u7136\u76f4\u63a5\u66ff\u6362<\/p>\n<p style=\"text-align: left\">\u66ff\u6362\u7684\u8fc7\u7a0b\u4e3b\u8981\u662f\u4e00\u4e2acreateElm\u51fd\u6570 \u53e6\u5916\u5219\u662f\u9500\u6bc1oldVNode<\/p>\n<pre>\/\/ destroy old node\r\n    if (isDef(parentElm)) {\r\n     removeVnodes(parentElm, [oldVnode], 0, 0)\r\n    } else if (isDef(oldVnode.tag)) {\r\n     invokeDestroyHook(oldVnode)\r\n    }<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p style=\"text-align: left\">\u63d2\u5165\u8fc7\u7a0b\u7b80\u5316\u6765\u8bf4\u5c31\u662f\u5224\u65adnode\u7684type\u5206\u522b\u8c03\u7528<\/p>\n<p style=\"text-align: left\">createComponent\uff08\u4f1a\u5224\u65ad\u662f\u5426\u6709children\u7136\u540e\u9012\u5f52\u8c03\u7528\uff09<\/p>\n<p style=\"text-align: left\">createComment<\/p>\n<p style=\"text-align: left\">createTextNode<\/p>\n<p style=\"text-align: left\">\u521b\u5efa\u540e\u4f7f\u7528insert\u51fd\u6570<\/p>\n<p style=\"text-align: left\">\u4e4b\u540e\u9700\u8981\u7528hydrate\u51fd\u6570\u5c06\u865a\u62dfdom\u548c\u771f\u662fdom\u8fdb\u884c\u6620\u5c04<\/p>\n<pre>function insert (parent, elm, ref) {\r\n  if (isDef(parent)) {\r\n   if (isDef(ref)) {\r\n    if (ref.parentNode === parent) {\r\n     nodeOps.insertBefore(parent, elm, ref)\r\n    }\r\n   } else {\r\n    nodeOps.appendChild(parent, elm)\r\n   }\r\n  }\r\n }<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p style=\"text-align: left\"><strong>\u6838\u5fc3\u51fd\u6570 <\/strong><\/p>\n<pre> function patchVnode (oldVnode, vnode, insertedVnodeQueue, removeOnly) {\r\n  if (oldVnode === vnode) {\r\n   return\r\n  }\r\n  const elm = vnode.elm = oldVnode.elm\r\n  if (isTrue(oldVnode.isAsyncPlaceholder)) {\r\n   if (isDef(vnode.asyncFactory.resolved)) {\r\n    hydrate(oldVnode.elm, vnode, insertedVnodeQueue)\r\n   } else {\r\n    vnode.isAsyncPlaceholder = true\r\n   }\r\n   return\r\n  }\r\n  if (isTrue(vnode.isStatic) &amp;&amp;\r\n   isTrue(oldVnode.isStatic) &amp;&amp;\r\n   vnode.key === oldVnode.key &amp;&amp;\r\n   (isTrue(vnode.isCloned) || isTrue(vnode.isOnce))\r\n  ) {\r\n   vnode.componentInstance = oldVnode.componentInstance\r\n   return\r\n  }\r\n  let i\r\n  const data = vnode.data\r\n  if (isDef(data) &amp;&amp; isDef(i = data.hook) &amp;&amp; isDef(i = i.prepatch)) {\r\n   i(oldVnode, vnode)\r\n  }\r\n  const oldCh = oldVnode.children\r\n  const ch = vnode.children\r\n  if (isDef(data) &amp;&amp; isPatchable(vnode)) {\r\n   for (i = 0; i &lt; cbs.update.length; ++i) cbs.update[i](oldVnode, vnode)\r\n   if (isDef(i = data.hook) &amp;&amp; isDef(i = i.update)) i(oldVnode, vnode)\r\n  }\r\n  if (isUndef(vnode.text)) {\r\n   if (isDef(oldCh) &amp;&amp; isDef(ch)) {\r\n    if (oldCh !== ch) updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly)\r\n   } else if (isDef(ch)) {\r\n    if (isDef(oldVnode.text)) nodeOps.setTextContent(elm, '')\r\n    addVnodes(elm, null, ch, 0, ch.length - 1, insertedVnodeQueue)\r\n   } else if (isDef(oldCh)) {\r\n    removeVnodes(elm, oldCh, 0, oldCh.length - 1)\r\n   } else if (isDef(oldVnode.text)) {\r\n    nodeOps.setTextContent(elm, '')\r\n   }\r\n  } else if (oldVnode.text !== vnode.text) {\r\n   nodeOps.setTextContent(elm, vnode.text)\r\n  }\r\n  if (isDef(data)) {\r\n   if (isDef(i = data.hook) &amp;&amp; isDef(i = i.postpatch)) i(oldVnode, vnode)\r\n  }\r\n }<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<blockquote style=\"text-align: left\">\n<p style=\"text-align: left\">const el = vnode.el = oldVnode.el \u8fd9\u662f\u5f88\u91cd\u8981\u7684\u4e00\u6b65\uff0c\u8ba9vnode.el\u5f15\u7528\u5230\u73b0\u5728\u7684\u771f\u5b9edom\uff0c\u5f53el\u4fee\u6539\u65f6\uff0cvnode.el\u4f1a\u540c\u6b65\u53d8\u5316\u3002<\/p>\n<\/blockquote>\n<ol>\n<li>\n<p style=\"text-align: left\">\u6bd4\u8f83\u4e8c\u8005\u5f15\u7528\u662f\u5426\u4e00\u81f4<\/p>\n<\/li>\n<li>\n<p style=\"text-align: left\">\u4e4b\u540easyncFactory\u4e0d\u77e5\u9053\u662f\u505a\u4ec0\u4e48\u7684\uff0c\u6240\u4ee5\u8fd9\u4e2a\u6bd4\u8f83\u770b\u4e0d\u61c2<\/p>\n<\/li>\n<li>\n<p style=\"text-align: left\">\u8282\u70b9\u6bd4\u8f83key\uff0c\u76f8\u540c\u540e\u4e5f\u4e0d\u505a\u91cd\u65b0\u6e32\u67d3\uff0c\u76f4\u63a5\u62f7\u8d1dcomponentInstance\uff08once\u547d\u4ee4\u5728\u6b64\u751f\u6548\uff09<\/p>\n<\/li>\n<li>\n<p style=\"text-align: left\">\u5982\u679cvnode\u662f\u6587\u672c\u8282\u70b9\u6216\u6ce8\u91ca\u8282\u70b9\uff0c\u4f46\u662fvnode.text != oldVnode.text\u65f6\uff0c\u53ea\u9700\u8981\u66f4\u65b0vnode.elm\u7684\u6587\u672c\u5185\u5bb9\u5c31\u53ef\u4ee5<\/p>\n<\/li>\n<li>\n<p style=\"text-align: left\">children\u7684\u6bd4\u8f83<\/p>\n<\/li>\n<\/ol>\n<ul>\n<li>\n<p style=\"text-align: left\">\u5982\u679c\u53ea\u6709oldVnode\u6709\u5b50\u8282\u70b9\uff0c\u90a3\u5c31\u628a\u8fd9\u4e9b\u8282\u70b9\u90fd\u5220\u9664<\/p>\n<\/li>\n<li>\n<p style=\"text-align: left\">\u5982\u679c\u53ea\u6709vnode\u6709\u5b50\u8282\u70b9\uff0c\u90a3\u5c31\u521b\u5efa\u8fd9\u4e9b\u5b50\u8282\u70b9\uff0c\u8fd9\u91cc\u5982\u679coldVnode\u662f\u4e2a\u6587\u672c\u8282\u70b9\u5c31\u628avnode.elm\u7684\u6587\u672c\u8bbe\u7f6e\u4e3a\u7a7a<\/p>\n<\/li>\n<li>\n<p style=\"text-align: left\">\u90fd\u6709\u5219updateChildren\uff0c\u8fd9\u4e2a\u4e4b\u540e\u8be6\u8ff0<\/p>\n<\/li>\n<li>\n<p style=\"text-align: left\">\u5982\u679coldVnode\u548cvnode\u90fd\u6ca1\u6709\u5b50\u8282\u70b9\uff0c\u4f46\u662foldVnode\u662f\u6587\u672c\u8282\u70b9\u6216\u6ce8\u91ca\u8282\u70b9\uff0c\u5c31\u628avnode.elm\u7684\u6587\u672c\u8bbe\u7f6e\u4e3a\u7a7a\u5b57\u7b26\u4e32<\/p>\n<\/li>\n<\/ul>\n<p style=\"text-align: left\"><strong>updateChildren<\/strong><\/p>\n<p style=\"text-align: left\">\u8fd9\u90e8\u5206\u91cd\u70b9\u8fd8\u662f\u5173\u6ce8\u6574\u4e2a\u7b97\u6cd5<\/p>\n<p style=\"text-align: left\">\u9996\u5148\u56db\u4e2a\u6307\u9488\uff0coldStart\uff0coldEnd\uff0cnewStart\uff0cnewEnd\uff0c\u4e24\u4e2a\u6570\u7ec4\uff0coldVnode\uff0cVnode\u3002<\/p>\n<pre>function updateChildren (parentElm, oldCh, newCh, insertedVnodeQueue, removeOnly) {\r\n  let oldStartIdx = 0\r\n  let newStartIdx = 0\r\n  let oldEndIdx = oldCh.length - 1\r\n  let oldStartVnode = oldCh[0]\r\n  let oldEndVnode = oldCh[oldEndIdx]\r\n  let newEndIdx = newCh.length - 1\r\n  let newStartVnode = newCh[0]\r\n  let newEndVnode = newCh[newEndIdx]\r\n  let oldKeyToIdx, idxInOld, vnodeToMove, refElm\r\n  while (oldStartIdx &lt;= oldEndIdx &amp;&amp; newStartIdx &lt;= newEndIdx) {\r\n   if (isUndef(oldStartVnode)) {\r\n    oldStartVnode = oldCh[++oldStartIdx] \/\/ Vnode has been moved left\r\n   } else if (isUndef(oldEndVnode)) {\r\n    oldEndVnode = oldCh[--oldEndIdx]\r\n   } else if (sameVnode(oldStartVnode, newStartVnode)) {\r\n    patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue)\r\n    oldStartVnode = oldCh[++oldStartIdx]\r\n    newStartVnode = newCh[++newStartIdx]\r\n   } else if (sameVnode(oldEndVnode, newEndVnode)) {\r\n    patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue)\r\n    oldEndVnode = oldCh[--oldEndIdx]\r\n    newEndVnode = newCh[--newEndIdx]\r\n   } else if (sameVnode(oldStartVnode, newEndVnode)) { \/\/ Vnode moved right\r\n    patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue)\r\n    canMove &amp;&amp; nodeOps.insertBefore(parentElm, oldStartVnode.elm, nodeOps.nextSibling(oldEndVnode.elm))\r\n    oldStartVnode = oldCh[++oldStartIdx]\r\n    newEndVnode = newCh[--newEndIdx]\r\n   } else if (sameVnode(oldEndVnode, newStartVnode)) { \/\/ Vnode moved left\r\n    patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue)\r\n    canMove &amp;&amp; nodeOps.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm)\r\n    oldEndVnode = oldCh[--oldEndIdx]\r\n    newStartVnode = newCh[++newStartIdx]\r\n   } else {\r\n    if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)\r\n    idxInOld = isDef(newStartVnode.key)\r\n     ? oldKeyToIdx[newStartVnode.key]\r\n     : findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx)\r\n    if (isUndef(idxInOld)) { \/\/ New element\r\n     createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm, false, newCh, newStartIdx)\r\n    } else {\r\n     vnodeToMove = oldCh[idxInOld]\r\n     if (sameVnode(vnodeToMove, newStartVnode)) {\r\n      patchVnode(vnodeToMove, newStartVnode, insertedVnodeQueue)\r\n      oldCh[idxInOld] = undefined\r\n      canMove &amp;&amp; nodeOps.insertBefore(parentElm, vnodeToMove.elm, oldStartVnode.elm)\r\n     } else {\r\n      \/\/ same key but different element. treat as new element\r\n      createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm, false, newCh, newStartIdx)\r\n     }\r\n    }\r\n    newStartVnode = newCh[++newStartIdx]\r\n   }\r\n  }\r\n  if (oldStartIdx &gt; oldEndIdx) {\r\n   refElm = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm\r\n   addVnodes(parentElm, refElm, newCh, newStartIdx, newEndIdx, insertedVnodeQueue)\r\n  } else if (newStartIdx &gt; newEndIdx) {\r\n   removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx)\r\n  }\r\n }<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p style=\"text-align: left\">\u4e00\u4e2a\u5faa\u73af\u6bd4\u8f83\u7684\u51e0\u79cd\u60c5\u51b5\u548c\u5904\u7406\uff08\u4ee5\u4e0b\u7684++ &#8211;\u5747\u6307index\u7684++ &#8211;\uff09\u6bd4\u8f83\u5219\u662f\u6bd4\u8f83\u7684node\u8282\u70b9\uff0c\u7b80\u7565\u5199\u6cd5 \u4e0d\u4e25\u8c28 \u6bd4\u8f83\u7528\u7684\u662fsameVnode\u51fd\u6570\u4e5f\u4e0d\u662f\u771f\u7684\u5168\u7b49<\/p>\n<p style=\"text-align: left\">\u6574\u4f53\u5faa\u73af\u4e0d\u7ed3\u675f\u7684\u6761\u4ef6oldStartIdx <\/p>\n<ol>\n<li>\n<p style=\"text-align: left\">oldStart === newStart\uff0coldStart++ newStart++<\/p>\n<\/li>\n<li>\n<p style=\"text-align: left\">oldEnd === newEnd\uff0coldEnd&#8211; newEnd&#8211;<\/p>\n<\/li>\n<li>\n<p style=\"text-align: left\">oldStart === newEnd, oldStart\u63d2\u5230\u961f\u4f0d\u672b\u5c3e oldStart++ newEnd&#8211;<\/p>\n<\/li>\n<li>\n<p style=\"text-align: left\">oldEnd === newStart, oldEnd\u63d2\u5230\u961f\u4f0d\u5f00\u5934 oldEnd&#8211; newStart++<\/p>\n<\/li>\n<li>\n<p style=\"text-align: left\">\u5269\u4e0b\u7684\u6240\u6709\u60c5\u51b5\u90fd\u8d70\u8fd9\u4e2a\u5904\u7406\u7b80\u5355\u7684\u8bf4\u4e5f\u5c31\u4e24\u79cd\u5904\u7406\uff0c\u5904\u7406\u540enewStart++<\/p>\n<\/li>\n<\/ol>\n<ul>\n<li>\n<p style=\"text-align: left\">newStart\u5728old\u4e2d\u53d1\u73b0\u4e00\u6837\u7684\u90a3\u4e48\u5c06\u8fd9\u4e2a\u79fb\u52a8\u5230oldStart\u524d<\/p>\n<\/li>\n<li>\n<p style=\"text-align: left\">\u6ca1\u6709\u53d1\u73b0\u4e00\u6837\u7684\u90a3\u4e48\u521b\u5efa\u4e00\u4e2a\u653e\u5230oldStart\u4e4b\u524d<\/p>\n<\/li>\n<\/ul>\n<p style=\"text-align: left\">\u5faa\u73af\u7ed3\u675f\u540e\u5e76\u6ca1\u6709\u5b8c\u6210<\/p>\n<p style=\"text-align: left\">\u8fd8\u6709\u4e00\u6bb5\u5224\u65ad\u624d\u7b97\u5b8c<\/p>\n<pre>if (oldStartIdx &gt; oldEndIdx) {\r\n   refElm = isUndef(newCh[newEndIdx + 1]) ? null : newCh[newEndIdx + 1].elm\r\n   addVnodes(parentElm, refElm, newCh, newStartIdx, newEndIdx, insertedVnodeQueue)\r\n  } else if (newStartIdx &gt; newEndIdx) {\r\n   removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx)\r\n  }<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p style=\"text-align: left\">\u7b80\u5355\u7684\u8bf4\u5c31\u662f\u5faa\u73af\u7ed3\u675f\u540e\uff0c\u770b\u56db\u4e2a\u6307\u9488\u4e2d\u95f4\u7684\u5185\u5bb9\uff0cold\u6570\u7ec4\u4e2d\u548cnew\u6570\u7ec4\u4e2d\uff0c\u591a\u9000\u5c11\u8865\u800c\u5df2<\/p>\n<p style=\"text-align: left\">\n<p>\u76f8\u4fe1\u770b\u4e86\u672c\u6587\u6848\u4f8b\u4f60\u5df2\u7ecf\u638c\u63e1\u4e86\u65b9\u6cd5\uff0c\u66f4\u591a\u7cbe\u5f69\u8bf7\u5173\u6ce8\u7c73\u4e91\u5176\u5b83\u76f8\u5173\u6587\u7ae0\uff01<\/p>\n<p>\u63a8\u8350\u9605\u8bfb\uff1a<\/p>\n<p><\/p>\n<p><\/p>\n<p><\/p>\n<p>\u4ee5\u4e0a\u5c31\u662fdiff\u7684\u5bf9\u8c61\u662f\u865a\u62dfdom\u7684\u8be6\u7ec6\u5185\u5bb9\uff0c\u66f4\u591a\u8bf7\u5173\u6ce8\u7c73\u4e91\u5176\u5b83\u76f8\u5173\u6587\u7ae0\uff01<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u8fd9\u6b21\u7ed9\u5927\u5bb6\u5e26\u6765diff\u7684\u5bf9\u8c61\u662f\u865a\u62dfdom\uff0c\u4f7f\u7528diff\u865a\u62df\u7684\u6709\u54ea\u4e9b\uff0c\u4e0b\u9762\u5c31\u662f\u5b9e\u6218\u6848\u4f8b\uff0c\u4e00\u8d77\u6765\u770b\u4e00\u4e0b\u3002 \u865a\u62dfdom diff\u7b97\u6cd5\u9996\u5148\u8981\u660e\u786e\u4e00\u4e2a\u6982\u5ff5\u5c31\u662fdiff\u7684\u5bf9\u8c61\u662f\u865a\u62dfdom\uff0c\u66f4\u65b0\u771f\u5b9edom\u5219\u662fdiff\u7b97\u6cd5\u7684\u7ed3\u679c Vnode\u57fa\u7c7b constructor ( \u3002\u3002\u3002 ) { this.tag = tag this.data = data this.children = children this.text = text this.elm = elm this.ns = undefined this.context = context this.fnContext = undefined this.fnOptions = undefined this.fnScopeId = undefined this.key = data &amp;&amp; data.key this.componentOptions = componentOptions this.componentInstance = undefined this.parent = undefined this.raw = [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[19],"tags":[],"class_list":["post-31468","post","type-post","status-publish","format-standard","hentry","category-19"],"_links":{"self":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/posts\/31468","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/comments?post=31468"}],"version-history":[{"count":0,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/posts\/31468\/revisions"}],"wp:attachment":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/media?parent=31468"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/categories?post=31468"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/tags?post=31468"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}