Fix keys, normalize holes (#2452)
* Fix #2434 * Treat holes as unkeyed, normalize boolean/null/undefined This brings a lot better consistency with that API, even though it's slightly breaking. (I had to update a bunch of tests to correspond with it.) * Fill in PR number [skip ci]
This commit is contained in:
parent
86d64e213f
commit
6c562d2b9b
12 changed files with 200 additions and 182 deletions
|
|
@ -45,6 +45,15 @@
|
|||
- Previously, it was only set for all non-`GET` methods and only when `useBody: true` was passed (the default), and it was always set for them. Now it's automatically omitted when no body is present, so the hole is slightly broadened.
|
||||
- route: query parameters in hash strings are no longer supported ([#2448](https://github.com/MithrilJS/mithril.js/pull/2448) [@isiahmeadows](https://github.com/isiahmeadows))
|
||||
- It's technically invalid in hashes, so I'd rather push people to keep in line with spec.
|
||||
- render: validate all elements are either keyed or unkeyed, and treat `null`/`undefined`/booleans as strictly unkeyed ([#2452](https://github.com/MithrilJS/mithril.js/pull/2452) [@isiahmeadows](https://github.com/isiahmeadows))
|
||||
- Gives a nice little perf boost with keyed fragments.
|
||||
- Minor, but imperceptible impact (within the margin of error) with unkeyed fragments.
|
||||
- Also makes the model a lot more consistent - all values are either keyed or unkeyed.
|
||||
- vnodes: normalize boolean children to `null`/`undefined` at the vnode level, always stringify non-object children that aren't holes ([#2452](https://github.com/MithrilJS/mithril.js/pull/2452) [@isiahmeadows](https://github.com/isiahmeadows))
|
||||
- Previously, `true` was equivalent to `"true"` and `false` was equivalent to `""`.
|
||||
- Previously, numeric children weren't coerced. Now, they are.
|
||||
- Unlikely to break most components, but it *could* break some users.
|
||||
- This increases consistency with how booleans are handled with children, so it should be more intuitive.
|
||||
|
||||
#### News
|
||||
|
||||
|
|
@ -101,6 +110,7 @@
|
|||
- route: arbitrary prefixes are properly supported now, including odd prefixes like `?#` and invalid prefixes like `#foo#bar` ([#2448](https://github.com/MithrilJS/mithril.js/pull/2448) [@isiahmeadows](https://github.com/isiahmeadows))
|
||||
- request: correct IE workaround for response type non-support ([#2449](https://github.com/MithrilJS/mithril.js/pull/2449) [@isiahmeadows](https://github.com/isiahmeadows))
|
||||
- render: correct `contenteditable` check to also check for `contentEditable` property name ([#2450](https://github.com/MithrilJS/mithril.js/pull/2450) [@isiahmeadows](https://github.com/isiahmeadows))
|
||||
- docs: clarify valid key usage ([#2452](https://github.com/MithrilJS/mithril.js/pull/2452) [@isiahmeadows](https://github.com/isiahmeadows))
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ m("button", {
|
|||
|
||||
If the value of such an attribute is `null` or `undefined`, it is treated as if the attribute was absent.
|
||||
|
||||
If there are class names in both first and second arguments of `m()`, they are merged together as you would expect. If the value of the class in the second argument is `null`or `undefined`, it is ignored.
|
||||
If there are class names in both first and second arguments of `m()`, they are merged together as you would expect. If the value of the class in the second argument is `null` or `undefined`, it is ignored.
|
||||
|
||||
If another attribute is present in both the first and the second argument, the second one takes precedence even if it is is `null` or `undefined`.
|
||||
|
||||
|
|
|
|||
25
docs/keys.md
25
docs/keys.md
|
|
@ -75,6 +75,27 @@ function correctUserList(users) {
|
|||
}
|
||||
```
|
||||
|
||||
Also, you might want to reinitialize a component. You can use the common pattern of a single-item keyed fragment where you change the key to destroy and reinitialize the element.
|
||||
|
||||
```javascript
|
||||
function ResettableToggle() {
|
||||
var toggleKey = false
|
||||
|
||||
function reset() {
|
||||
toggleKey = !toggleKey
|
||||
}
|
||||
|
||||
return {
|
||||
view: function() {
|
||||
return [
|
||||
m("button", {onclick: reset}, "Reset toggle"),
|
||||
[m(Toggle, {key: toggleKey})]
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Debugging key related issues
|
||||
|
|
@ -178,6 +199,10 @@ m("div", [
|
|||
])
|
||||
```
|
||||
|
||||
In fact, this will cause an error to be thrown, to remind you to not do it. So don't do it!
|
||||
|
||||
Note that `null`s, `undefined`s, and booleans are considered unkeyed nodes. If you want the keyed equivalent, use `m.fragment({key: ...}, [])`, a keyed empty fragment.
|
||||
|
||||
#### Avoid passing model data directly to components if the model uses `key` as a data property
|
||||
|
||||
The `key` property may appear in your data model in a way that conflicts with Mithril's key logic. For example, a component may represent an entity whose `key` property is expected to change over time. This can lead to components receiving the wrong data, re-initialize, or change positions unexpectedly. If your data model uses the `key` property, make sure to wrap the data such that Mithril doesn't misinterpret it as a rendering instruction:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue