Fix custom elements attribute application, improve key checking

- Fix custom elements attribute application to acknowledge that not all
  custom elements operate purely based on attributes. (Plus, those
  blasted things are verbose as heck when you're working with them in
  raw form. It's also not that uncommon for functionality to be exposed
  via property and *not* attribute.)
- Don't memoize the normalized value when we 1. only use it once in each
  branch, and 2. only use it for a few special cases.
- Centralize the "has property key" code, so it's easier to tune and
  read. I also inlined a couple functions while I was at it since they
  were small and only used once.
- Actually test for how attributes are applied to raw DOM elements vs
  when we choose to use keys. When I first developed the patch, it
  silently worked, when I should've been breaking things.
This commit is contained in:
Isiah Meadows 2018-08-31 22:54:21 -04:00
parent f844cc8134
commit 1ecc30a064
6 changed files with 217 additions and 41 deletions

View file

@ -178,6 +178,76 @@ m("input[readonly]")
m("input[readOnly]")
```
This even includes custom elements. For example, you can use [A-Frame](https://aframe.io/docs/0.8.0/introduction/) within Mithril, no problem!
```javascript
m("a-scene", [
m("a-box", {
position: "-1 0.5 -3",
rotation: "0 45 0",
color: "#4CC3D9",
}),
m("a-sphere", {
position: "0 1.25 -5",
radius: "1.25",
color: "#EF2D5E",
}),
m("a-cylinder", {
position: "1 0.75 -3",
radius: "0.5",
height: "1.5",
color: "#FFC65D",
}),
m("a-plane", {
position: "0 0 -4",
rotation: "-90 0 0",
width: "4",
height: "4",
color: "#7BC8A4",
}),
m("a-sky", {
color: "#ECECEC",
}),
])
```
And yes, this translates to both attributes and properties, and it works just like they would in the DOM. Using [Brick's `brick-deck`](http://brick.mozilla.io/docs/brick-deck) as an example, they have a `selected-index` attribute with a corresponding `selectedIndex` getter/setter property.
```javascript
m("brick-deck[selected-index=0]", [/* ... */]) // lowercase
m("brick-deck[selectedIndex=0]", [/* ... */]) // uppercase
// I know these look odd, but `brick-deck`'s `selectedIndex` property is a
// string, not a number.
m("brick-deck", {"selected-index": "0"}, [/* ... */])
m("brick-deck", {"selectedIndex": "0"}, [/* ... */])
```
For custom elements, it doesn't auto-stringify properties, in case they are objects, numbers, or some other non-string value. So assuming you had some custom element `my-special-element` that has an `elem.whitelist` array getter/setter property, you could do this, and it'd work as you'd expect:
```javascript
m("my-special-element", {
whitelist: [
"https://example.com",
"http://neverssl.com",
"https://google.com",
],
})
```
If you have classes or IDs for those elements, the shorthands still work as you would expect. To pull another A-Frame example:
```javascript
// These two are equivalent
m("a-entity#player")
m("a-entity", {id: "player"})
```
Do note that all the properties with magic semantics, like lifecycle attributes, `onevent` handlers, `key`s, `class`, and `style`, those are still treated the same way they are for normal HTML elements.
---
### Style attribute
@ -192,7 +262,7 @@ m("div[style=background:red]")
Using a string as a `style` would overwrite all inline styles in the element if it is redrawn, and not only CSS rules whose values have changed.
Mithril does not attempt to add units to number values.
Mithril does not attempt to add units to number values. It simply stringifies them.
---