Просмотр исходного кода

slightly improve ssr hydration performance

Evan You 9 лет назад
Родитель
Сommit
929c16f3dd
2 измененных файлов с 24 добавлено и 19 удалено
  1. 24 15
      src/core/vdom/patch.js
  2. 0 4
      src/platforms/weex/runtime/node-ops.js

+ 24 - 15
src/core/vdom/patch.js

@@ -14,7 +14,7 @@
 
 import config from '../config'
 import VNode from './vnode'
-import { isPrimitive, _toString, warn } from '../util/index'
+import { makeMap, isPrimitive, _toString, warn } from '../util/index'
 import { activeInstance } from '../instance/lifecycle'
 import { registerRef } from './modules/ref'
 
@@ -468,6 +468,11 @@ export function createPatchFunction (backend) {
   }
 
   let bailed = false
+  // list of modules that can skip create hook during hydration because they
+  // are already rendered on the client or has no need for initialization
+  const isRenderedModule = makeMap('attrs,style,class,staticClass,staticStyle,key')
+
+  // Note: this is a browser-only function so we can assume elms are DOM nodes.
   function hydrate (elm, vnode, insertedVnodeQueue) {
     if (process.env.NODE_ENV !== 'production') {
       if (!assertNodeMatch(elm, vnode)) {
@@ -486,36 +491,40 @@ export function createPatchFunction (backend) {
     }
     if (isDef(tag)) {
       if (isDef(children)) {
-        const childNodes = nodeOps.childNodes(elm)
         // empty element, allow client to pick up and populate children
-        if (!childNodes.length) {
+        if (!elm.hasChildNodes()) {
           createChildren(vnode, children, insertedVnodeQueue)
         } else {
           let childrenMatch = true
-          if (childNodes.length !== children.length) {
-            childrenMatch = false
-          } else {
-            for (let i = 0; i < children.length; i++) {
-              if (!hydrate(childNodes[i], children[i], insertedVnodeQueue)) {
-                childrenMatch = false
-                break
-              }
+          let childNode = elm.firstChild
+          for (let i = 0; i < children.length; i++) {
+            if (!childNode || !hydrate(childNode, children[i], insertedVnodeQueue)) {
+              childrenMatch = false
+              break
             }
+            childNode = childNode.nextSibling
           }
-          if (!childrenMatch) {
+          // if childNode is not null, it means the actual childNodes list is
+          // longer than the virtual children list.
+          if (!childrenMatch || childNode) {
             if (process.env.NODE_ENV !== 'production' &&
                 typeof console !== 'undefined' &&
                 !bailed) {
               bailed = true
               console.warn('Parent: ', elm)
-              console.warn('Mismatching childNodes vs. VNodes: ', childNodes, children)
+              console.warn('Mismatching childNodes vs. VNodes: ', elm.childNodes, children)
             }
             return false
           }
         }
       }
       if (isDef(data)) {
-        invokeCreateHooks(vnode, insertedVnodeQueue)
+        for (const key in data) {
+          if (!isRenderedModule(key)) {
+            invokeCreateHooks(vnode, insertedVnodeQueue)
+            break
+          }
+        }
       }
     }
     return true
@@ -525,7 +534,7 @@ export function createPatchFunction (backend) {
     if (vnode.tag) {
       return (
         vnode.tag.indexOf('vue-component') === 0 ||
-        vnode.tag.toLowerCase() === nodeOps.tagName(node).toLowerCase()
+        vnode.tag.toLowerCase() === node.tagName.toLowerCase()
       )
     } else {
       return _toString(vnode.text) === node.data

+ 0 - 4
src/platforms/weex/runtime/node-ops.js

@@ -69,10 +69,6 @@ export function setTextContent (node, text) {
   node.parentNode.setAttr('value', text)
 }
 
-export function childNodes (node) {
-  return node.pureChildren
-}
-
 export function setAttribute (node, key, val) {
   node.setAttr(key, val)
 }