diff --git a/docs/change-log.md b/docs/change-log.md index 6ea8b86a..82686f0e 100644 --- a/docs/change-log.md +++ b/docs/change-log.md @@ -27,6 +27,7 @@ - API: `m.route.set()` causes all mount points to be redrawn ([#1592](https://github.com/MithrilJS/mithril.js/pull/1592)) - API: If a user sets the Content-Type header within a request's options, that value will be the entire header value rather than being appended to the default value ([#1924](https://github.com/MithrilJS/mithril.js/pull/1924)) +- API: Using style objects in hyperscript calls will now properly diff style properties from one render to another as opposed to re-writing all element style properties every render. --- diff --git a/render/render.js b/render/render.js index 6bebd212..f6782297 100644 --- a/render/render.js +++ b/render/render.js @@ -552,6 +552,18 @@ module.exports = function($window) { //style function updateStyle(element, old, style) { + if (old != null && style != null && typeof old === "object" && typeof style === "object" && style !== old) { + // Both old & new are (different) objects. + // Update style properties that have changed + for (var key in style) { + if (style[key] !== old[key]) element.style[key] = style[key] + } + // Remove style properties that no longer exist + for (var key in old) { + if (!(key in style)) element.style[key] = "" + } + return + } if (old === style) element.style.cssText = "", old = null if (style == null) element.style.cssText = "" else if (typeof style === "string") element.style.cssText = style @@ -560,11 +572,6 @@ module.exports = function($window) { for (var key in style) { element.style[key] = style[key] } - if (old != null && typeof old !== "string") { - for (var key in old) { - if (!(key in style)) element.style[key] = "" - } - } } } diff --git a/render/tests/test-updateElement.js b/render/tests/test-updateElement.js index 313fe1a9..a2ae0fcb 100644 --- a/render/tests/test-updateElement.js +++ b/render/tests/test-updateElement.js @@ -192,6 +192,19 @@ o.spec("updateElement", function() { o(updated.dom.style.backgroundColor).equals("") o(updated.dom.style.color).equals("gold") }) + o("does not re-render element styles for equivalent style objects", function() { + var style = {color: "gold"} + var vnode = {tag: "a", attrs: {style: style}} + + render(root, [vnode]) + + root.firstChild.style.color = "red" + style = {color: "gold"} + var updated = {tag: "a", attrs: {style: style}} + render(root, [updated]) + + o(updated.dom.style.color).equals("red") + }) o("replaces el", function() { var vnode = {tag: "a"} var updated = {tag: "b"}