Fix style updates to avoid unnecessary allocation (#2312)

* Fix style updates to avoid unnecessary allocation

- Drive-by: properly censor `cssFloat` -> css `float:` to match DOM
  behavior

* Document `style` syntax + custom property support. [skip ci]

* Add a missing test

* Add a few more descriptive comments.

* Update changelog [skip ci]
This commit is contained in:
Isiah Meadows 2018-12-03 14:31:08 -05:00 committed by GitHub
parent b25e8e15a0
commit 8134c51a48
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 41 additions and 25 deletions

View file

@ -775,38 +775,45 @@ module.exports = function($window) {
) && key in vnode.dom
}
var matchUpperCase = /[A-Z]/g
function prependDashAndLowerCase(string){
return "-" + string.toLowerCase()
}
function normalizeProp(prop) {
return "-" && prop[1] === "-"
? prop
: prop.replace(matchUpperCase, prependDashAndLowerCase)
}
//style
var uppercaseRegex = /[A-Z]/g
function toLowerCase(capital) { return "-" + capital.toLowerCase() }
function normalizeKey(key) {
return key[0] === "-" && key[1] === "-" ? key :
key === "cssFloat" ? "float" :
key.replace(uppercaseRegex, toLowerCase)
}
function updateStyle(element, old, style) {
if (old != null && style != null && typeof old === "object" && typeof style === "object" && style !== old) {
if (old === style) {
// Styles are equivalent, do nothing.
} else if (style == null) {
// New style is missing, just clear it.
element.style.cssText = ""
} else if (typeof style !== "object") {
// New style is a string, let engine deal with patching.
element.style.cssText = style
} else if (old == null || typeof old !== "object") {
// `old` is missing or a string, `style` is an object.
element.style.cssText = ""
// Add new style properties
for (var key in style) {
var value = style[key]
if (value != null) element.style.setProperty(normalizeKey(key), String(value))
}
} else {
// Both old & new are (different) objects.
// Update style properties that have changed
for (var key in style) {
if (style[key] !== old[key]) element.style.setProperty(normalizeProp(key), style[key])
var value = style[key]
if (value != null && (value = String(value)) !== String(old[key])) {
element.style.setProperty(normalizeKey(key), value)
}
}
// Remove style properties that no longer exist
for (var key in old) {
if (!(key in style)) element.style.removeProperty(normalizeProp(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
else {
if (typeof old === "string") element.style.cssText = ""
for (var key in style) {
element.style.setProperty(normalizeProp(key), style[key])
if (old[key] != null && style[key] == null) {
element.style.removeProperty(normalizeKey(key))
}
}
}
}

View file

@ -45,6 +45,13 @@ o.spec("createElement", function() {
o(vnode.dom.style["--cssVar"]).equals("red")
})
o("censors cssFloat to float", function() {
var vnode = {tag: "a", attrs: {style: {cssFloat: "left"}}}
render(root, [vnode])
o(vnode.dom.style.float).equals("left")
})
o("creates children", function() {
var vnode = {tag: "div", children: [{tag: "a"}, {tag: "b"}]}
render(root, [vnode])