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

make vdom hot code more explicit and vm friendly

Evan You 9 лет назад
Родитель
Сommit
d3aee4ea4e
4 измененных файлов с 54 добавлено и 32 удалено
  1. 17 10
      src/core/vdom/create-component.js
  2. 13 8
      src/core/vdom/create-element.js
  3. 10 14
      src/core/vdom/patch.js
  4. 14 0
      src/shared/util.js

+ 17 - 10
src/core/vdom/create-component.js

@@ -7,6 +7,9 @@ import { resolveSlots } from '../instance/render-helpers/resolve-slots'
 
 import {
   warn,
+  isDef,
+  isUndef,
+  isTrue,
   isObject,
   validateProp
 } from '../util/index'
@@ -83,21 +86,25 @@ const componentVNodeHooks = {
 const hooksToMerge = Object.keys(componentVNodeHooks)
 
 export function createComponent (
-  Ctor: Class<Component> | Function | Object | void,
+  Ctor: any,
   data?: VNodeData,
   context: Component,
   children: ?Array<VNode>,
   tag?: string
 ): VNode | void {
-  if (!Ctor) {
+  if (isUndef(Ctor)) {
     return
   }
 
   const baseCtor = context.$options._base
+
+  // plain options object: turn it into a constructor
   if (isObject(Ctor)) {
     Ctor = baseCtor.extend(Ctor)
   }
 
+  // if at this stage it's not a constructor or an async component factory,
+  // reject.
   if (typeof Ctor !== 'function') {
     if (process.env.NODE_ENV !== 'production') {
       warn(`Invalid Component definition: ${String(Ctor)}`, context)
@@ -106,8 +113,8 @@ export function createComponent (
   }
 
   // async component
-  if (!Ctor.cid) {
-    if (Ctor.resolved) {
+  if (isUndef(Ctor.cid)) {
+    if (isDef(Ctor.resolved)) {
       Ctor = Ctor.resolved
     } else {
       Ctor = resolveAsyncComponent(Ctor, baseCtor, () => {
@@ -130,7 +137,7 @@ export function createComponent (
   data = data || {}
 
   // transform component v-model data into props & events
-  if (data.model) {
+  if (isDef(data.model)) {
     transformModel(Ctor.options, data)
   }
 
@@ -138,7 +145,7 @@ export function createComponent (
   const propsData = extractPropsFromVNodeData(data, Ctor, tag)
 
   // functional component
-  if (Ctor.options.functional) {
+  if (isTrue(Ctor.options.functional)) {
     return createFunctionalComponent(Ctor, propsData, data, context, children)
   }
 
@@ -148,7 +155,7 @@ export function createComponent (
   // replace with listeners with .native modifier
   data.on = data.nativeOn
 
-  if (Ctor.options.abstract) {
+  if (isTrue(Ctor.options.abstract)) {
     // abstract components do not keep anything
     // other than props & listeners
     data = {}
@@ -176,7 +183,7 @@ function createFunctionalComponent (
 ): VNode | void {
   const props = {}
   const propOptions = Ctor.options.props
-  if (propOptions) {
+  if (isDef(propOptions)) {
     for (const key in propOptions) {
       props[key] = validateProp(key, propOptions, propsData)
     }
@@ -221,7 +228,7 @@ export function createComponentInstanceForVnode (
   }
   // check inline-template render functions
   const inlineTemplate = vnode.data.inlineTemplate
-  if (inlineTemplate) {
+  if (isDef(inlineTemplate)) {
     options.render = inlineTemplate.render
     options.staticRenderFns = inlineTemplate.staticRenderFns
   }
@@ -254,7 +261,7 @@ function transformModel (options, data: any) {
   const event = (options.model && options.model.event) || 'input'
   ;(data.props || (data.props = {}))[prop] = data.model.value
   const on = data.on || (data.on = {})
-  if (on[event]) {
+  if (isDef(on[event])) {
     on[event] = [data.model.callback].concat(on[event])
   } else {
     on[event] = data.model.callback

+ 13 - 8
src/core/vdom/create-element.js

@@ -6,8 +6,11 @@ import { createComponent } from './create-component'
 
 import {
   warn,
-  resolveAsset,
-  isPrimitive
+  isDef,
+  isUndef,
+  isTrue,
+  isPrimitive,
+  resolveAsset
 } from '../util/index'
 
 import {
@@ -33,7 +36,9 @@ export function createElement (
     children = data
     data = undefined
   }
-  if (alwaysNormalize) normalizationType = ALWAYS_NORMALIZE
+  if (isTrue(alwaysNormalize)) {
+    normalizationType = ALWAYS_NORMALIZE
+  }
   return _createElement(context, tag, data, children, normalizationType)
 }
 
@@ -44,7 +49,7 @@ export function _createElement (
   children?: any,
   normalizationType?: number
 ): VNode {
-  if (data && data.__ob__) {
+  if (isDef(data) && isDef((data: any).__ob__)) {
     process.env.NODE_ENV !== 'production' && warn(
       `Avoid using observed data object as vnode data: ${JSON.stringify(data)}\n` +
       'Always create fresh vnode data objects in each render!',
@@ -78,7 +83,7 @@ export function _createElement (
         config.parsePlatformTagName(tag), data, children,
         undefined, undefined, context
       )
-    } else if ((Ctor = resolveAsset(context.$options, 'components', tag))) {
+    } else if (isDef(Ctor = resolveAsset(context.$options, 'components', tag))) {
       // component
       vnode = createComponent(Ctor, data, context, children, tag)
     } else {
@@ -94,7 +99,7 @@ export function _createElement (
     // direct component options / constructor
     vnode = createComponent(tag, data, context, children)
   }
-  if (vnode) {
+  if (vnode !== undefined) {
     if (ns) applyNS(vnode, ns)
     return vnode
   } else {
@@ -108,10 +113,10 @@ function applyNS (vnode, ns) {
     // use default namespace inside foreignObject
     return
   }
-  if (vnode.children) {
+  if (Array.isArray(vnode.children)) {
     for (let i = 0, l = vnode.children.length; i < l; i++) {
       const child = vnode.children[i]
-      if (child.tag && !child.ns) {
+      if (isDef(child.tag) && isUndef(child.ns)) {
         applyNS(child, ns)
       }
     }

+ 10 - 14
src/core/vdom/patch.js

@@ -15,26 +15,22 @@
 import VNode from './vnode'
 import config from '../config'
 import { SSR_ATTR } from 'shared/util'
-import { makeMap, isPrimitive, warn } from '../util/index'
-import { activeInstance } from '../instance/lifecycle'
 import { registerRef } from './modules/ref'
+import { activeInstance } from '../instance/lifecycle'
+
+import {
+  warn,
+  isDef,
+  isUndef,
+  isTrue,
+  makeMap,
+  isPrimitive
+} from '../util/index'
 
 export const emptyNode = new VNode('', {}, [])
 
 const hooks = ['create', 'activate', 'update', 'remove', 'destroy']
 
-function isUndef (v) {
-  return v === undefined || v === null
-}
-
-function isDef (v) {
-  return v !== undefined && v !== null
-}
-
-function isTrue (v) {
-  return v === true
-}
-
 function sameVnode (a, b) {
   return (
     a.key === b.key &&

+ 14 - 0
src/shared/util.js

@@ -2,6 +2,20 @@
 
 export const SSR_ATTR = 'data-server-rendered'
 
+// these helpers produces better vm code in JS engines due to their
+// explicitness and function inlining
+export function isUndef (v: any): boolean {
+  return v === undefined || v === null
+}
+
+export function isDef (v: any): boolean {
+  return v !== undefined && v !== null
+}
+
+export function isTrue (v: any): boolean {
+  return v === true
+}
+
 /**
  * Convert a value to a string that is actually rendered.
  */