mroe docs

This commit is contained in:
Leo Horie 2016-05-25 02:01:27 -04:00
parent 5815a590a8
commit e35fc79f09
3 changed files with 264 additions and 3 deletions

View file

@ -2,6 +2,7 @@
- [What are keys](#what-are-keys)
- [How to use](#how-to-use)
- [Debugging key related issues](#debugging-key-related-issues)
---
@ -11,7 +12,7 @@ Keys are a mechanism that allows re-ordering DOM elements within a NodeList, and
In other words, a `key` is a way of saying "this DOM element is for the data object with this id".
Typically, `key` should be the unique identifier field of the objects in the data array.
Typically, a `key` property should be the unique identifier field of the objects in the data array.
```javascript
var users = [
@ -64,7 +65,7 @@ Worse still, if there were stateful jQuery plugins attached to these buttons, th
Even though in this particular example, we humans intuitively guess that the first item in the list was the one being removed, it's actually impossible for a computer to automatically solve this problem for all possible inputs.
Therefore, in the cases when a list of vnodes is derived from a *mutable* array of data, you should add a `key` property to each virtual node that maps to a uniquely identifiable field in the source data. This will allow Mithril to intelligently re-order the DOM to maintain each DOM element correctly mapped to its respective item in the data source.
Therefore, in the cases when a list of vnodes is derived from a dynamic array of data, you should add a `key` property to each virtual node that maps to a uniquely identifiable field in the source data. This will allow Mithril to intelligently re-order the DOM to maintain each DOM element correctly mapped to its respective item in the data source.
```javascript
function correctUserList(users) {
@ -74,7 +75,79 @@ function correctUserList(users) {
}
```
---
### Debugging key related issues
Keys can cause confusing issues if they are misunderstood. A typical symptom of key related issues is that application state appears to become corrupted after a few user interactions (usually involving a deletion).
#### Avoid wrapper elements around keyed elements
Keys must be placed on the virtual node that is an immediate child of the array. This means that if you wrap the `button` in an `div` in the example above, the key must be moved to the `div`.
```javascript
// AVOID
users.map(function(u) {
return m("div", [ //key should be in `div`
m("button", {key: u.id}, u.name)
])
})
```
#### Avoid hiding keys in component root elements
If you refactor the code and put the button inside a component, the key must be moved out of the component and placed back where the component took the place of the button.
```javascript
// AVOID
var Button = {
view: function(vnode) {
return m("button", {key: vnode.attrs.id}, u.name)
}
}
users.map(function(u) {
return m("div", [
m(Button, {id: u.id}, u.name) //key should be here, not in component
])
})
```
#### Avoid wrapping keyed elements in arrays
Arrays are [vnodes](vnodes.md), and therefore keyable. You should not wrap arrays around keyed elements
```javascript
// AVOID
users.map(function(u) {
return [ //fragment is a vnode, and therefore keyable
m("button", {key: u.id}, u.name)
]
})
// PREFER
users.map(function(u) {
return m("button", {key: u.id}, u.name)
})
// PREFER
users.map(function(u) {
return {tag: "[", key: u.id, children: [
m("button", u.name)
]}
})
```
#### Avoid variable types
Keys must be strings if present or they will be cast to strings if they are not. Therefore, `"1"` (string) and `1` (number) are considered the same key.
In addition, keys must be placed on the virtual node that is an immediate child of the array. This means that if you wrap the `button` in an `div` in the example above, the key must be moved to the `div`. Likewise, if you refactor the code and put the button inside a component, the key must be moved out of the component and placed back where the component took place of the button.
You should use either strings or numbers as keys in one array, but not mix both.
```javascript
// AVOID
var things = [
{id: "1", name: "Book"},
{id: 1, name: "Cup"},
]
```