ソースを参照

use more efficient deep update handling for dom modules

Evan You 10 年 前
コミット
621756e531

+ 7 - 3
src/platforms/web/runtime/modules/attrs.js

@@ -1,5 +1,6 @@
 /* @flow */
 
+import { extend } from 'shared/util'
 import {
   isBooleanAttr,
   isEnumeratedAttr,
@@ -16,11 +17,14 @@ function updateAttrs (oldVnode: VNodeWithData, vnode: VNodeWithData) {
   let key, cur, old
   const elm = vnode.elm
   const oldAttrs = oldVnode.data.attrs || {}
-  const attrs = vnode.data.attrs || {}
-  const clonedAttrs = vnode.data.attrs = {}
+  let attrs = vnode.data.attrs || {}
+  // clone observed objects, as the user probably wants to mutate it
+  if (attrs.__ob__) {
+    attrs = vnode.data.attrs = extend({}, attrs)
+  }
 
   for (key in attrs) {
-    cur = clonedAttrs[key] = attrs[key]
+    cur = attrs[key]
     old = oldAttrs[key]
     if (old !== cur) {
       setAttr(elm, key, cur)

+ 8 - 3
src/platforms/web/runtime/modules/dom-props.js

@@ -1,5 +1,7 @@
 /* @flow */
 
+import { extend } from 'shared/util'
+
 function updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) {
   if (!oldVnode.data.domProps && !vnode.data.domProps) {
     return
@@ -7,8 +9,11 @@ function updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) {
   let key, cur
   const elm: any = vnode.elm
   const oldProps = oldVnode.data.domProps || {}
-  const props = vnode.data.domProps || {}
-  const clonedProps = vnode.data.domProps = {}
+  let props = vnode.data.domProps || {}
+  // clone observed objects, as the user probably wants to mutate it
+  if (props.__ob__) {
+    props = vnode.data.domProps = extend({}, props)
+  }
 
   for (key in oldProps) {
     if (props[key] == null) {
@@ -16,7 +21,7 @@ function updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) {
     }
   }
   for (key in props) {
-    cur = clonedProps[key] = props[key]
+    cur = props[key]
     if (key === 'value') {
       // store value as _value as well since
       // non-string values will be stringified

+ 7 - 4
src/platforms/web/runtime/modules/style.js

@@ -1,6 +1,6 @@
 /* @flow */
 
-import { cached, camelize, toObject } from 'shared/util'
+import { cached, extend, camelize, toObject } from 'shared/util'
 
 const prefixes = ['Webkit', 'Moz', 'ms']
 
@@ -28,15 +28,18 @@ function updateStyle (oldVnode: VNodeWithData, vnode: VNodeWithData) {
   const elm: any = vnode.elm
   const oldStyle: any = oldVnode.data.style || {}
   let style = vnode.data.style || {}
+  const needClone = style.__ob__
 
   // handle array syntax
   if (Array.isArray(style)) {
-    style = toObject(style)
+    style = vnode.data.style = toObject(style)
   }
 
   // clone the style for future updates,
   // in case the user mutates the style object in-place.
-  const clonedStyle = vnode.data.style = {}
+  if (needClone) {
+    style = vnode.data.style = extend({}, style)
+  }
 
   for (name in oldStyle) {
     if (!style[name]) {
@@ -44,7 +47,7 @@ function updateStyle (oldVnode: VNodeWithData, vnode: VNodeWithData) {
     }
   }
   for (name in style) {
-    cur = clonedStyle[name] = style[name]
+    cur = style[name]
     if (cur !== oldStyle[name]) {
       // ie9 setting to null has no effect, must use empty string
       elm.style[normalize(name)] = cur || ''