Browse Source

tweak style merge for performance

Evan You 9 years ago
parent
commit
b69b4a4eef

+ 1 - 1
flow/vnode.js

@@ -37,7 +37,7 @@ declare interface VNodeData {
   tag?: string;
   staticClass?: string;
   class?: any;
-  staticStyle?: string;
+  staticStyle?: { [key: string]: any };
   style?: Array<Object> | Object;
   props?: { [key: string]: any };
   attrs?: { [key: string]: string };

+ 2 - 1
src/platforms/web/compiler/modules/style.js

@@ -1,6 +1,7 @@
 /* @flow */
 
 import { parseText } from 'compiler/parser/text-parser'
+import { parseStyleText } from 'web/util/style'
 import {
   getAndRemoveAttr,
   getBindingAttr,
@@ -22,7 +23,7 @@ function transformNode (el: ASTElement, options: CompilerOptions) {
         )
       }
     }
-    el.staticStyle = JSON.stringify(staticStyle)
+    el.staticStyle = JSON.stringify(parseStyleText(staticStyle))
   }
 
   const styleBinding = getBindingAttr(el, 'style', false /* getStatic */)

+ 5 - 9
src/platforms/web/runtime/modules/style.js

@@ -1,7 +1,7 @@
 /* @flow */
 
-import { cached, camelize, extend, looseEqual } from 'shared/util'
-import { normalizeBindingStyle, getStyle } from 'web/util/style'
+import { cached, camelize, extend } from 'shared/util'
+import { normalizeStyleBinding, getStyle } from 'web/util/style'
 
 const cssVarRE = /^--/
 const setProp = (el, name, val) => {
@@ -43,14 +43,11 @@ function updateStyle (oldVnode: VNodeWithData, vnode: VNodeWithData) {
   let cur, name
   const el: any = vnode.elm
   const oldStyle: any = oldVnode.data.style || {}
-  const style: Object = normalizeBindingStyle(vnode.data.style || {})
-  vnode.data.style = extend({}, style)
+  const style = normalizeStyleBinding(vnode.data.style) || {}
 
-  const newStyle: Object = getStyle(vnode, true)
+  vnode.data.style = style.__ob__ ? extend({}, style) : style
 
-  if (looseEqual(el._prevStyle, newStyle)) {
-    return
-  }
+  const newStyle = getStyle(vnode, true)
 
   for (name in oldStyle) {
     if (newStyle[name] == null) {
@@ -64,7 +61,6 @@ function updateStyle (oldVnode: VNodeWithData, vnode: VNodeWithData) {
       setProp(el, name, cur == null ? '' : cur)
     }
   }
-  el._prevStyle = newStyle
 }
 
 export default {

+ 25 - 17
src/platforms/web/util/style.js

@@ -2,7 +2,7 @@
 
 import { cached, extend, toObject } from 'shared/util'
 
-const parseStyleText = cached(function (cssText) {
+export const parseStyleText = cached(function (cssText) {
   const rs = {}
   if (!cssText) {
     return rs
@@ -20,17 +20,21 @@ const parseStyleText = cached(function (cssText) {
   return rs
 })
 
-function normalizeStyleData (styleData: Object): Object {
-  const style = normalizeBindingStyle(styleData.style)
-  const staticStyle = parseStyleText(styleData.staticStyle)
-  return extend(extend({}, staticStyle), style)
+// merge static and dynamic style data on the same vnode
+function normalizeStyleData (data: VNodeData): ?Object {
+  const style = normalizeStyleBinding(data.style)
+  // static style is pre-processed into an object during compilation
+  // and is always a fresh object, so it's safe to merge into it
+  return data.staticStyle
+    ? extend(data.staticStyle, style)
+    : style
 }
 
-export function normalizeBindingStyle (bindingStyle: any): Object {
+// normalize possible array / string values into Object
+export function normalizeStyleBinding (bindingStyle: any): ?Object {
   if (Array.isArray(bindingStyle)) {
     return toObject(bindingStyle)
   }
-
   if (typeof bindingStyle === 'string') {
     return parseStyleText(bindingStyle)
   }
@@ -42,25 +46,29 @@ export function normalizeBindingStyle (bindingStyle: any): Object {
  * so that parent component's style could override it
  */
 export function getStyle (vnode: VNode, checkChild: boolean): Object {
-  let data = vnode.data
-  let parentNode = vnode
-  let childNode = vnode
-
-  data = normalizeStyleData(data)
+  const res = {}
+  let styleData
 
   if (checkChild) {
+    let childNode = vnode
     while (childNode.child) {
       childNode = childNode.child._vnode
-      if (childNode.data) {
-        data = extend(normalizeStyleData(childNode.data), data)
+      if (childNode.data && (styleData = normalizeStyleData(childNode.data))) {
+        extend(res, styleData)
       }
     }
   }
+
+  if ((styleData = normalizeStyleData(vnode.data))) {
+    extend(res, styleData)
+  }
+
+  let parentNode = vnode
   while ((parentNode = parentNode.parent)) {
-    if (parentNode.data) {
-      data = extend(data, normalizeStyleData(parentNode.data))
+    if (parentNode.data && (styleData = normalizeStyleData(parentNode.data))) {
+      extend(res, styleData)
     }
   }
-  return data
+  return res
 }
 

+ 1 - 1
types/vnode.d.ts

@@ -38,7 +38,7 @@ export interface VNodeData {
   tag?: string;
   staticClass?: string;
   class?: any;
-  staticStyle?: string;
+  staticStyle?: { [key: string]: any };
   style?: Object[] | Object;
   props?: { [key: string]: any };
   attrs?: { [key: string]: any };