merge: next onto master
This commit is contained in:
commit
46ebb340d1
76 changed files with 3098 additions and 2017 deletions
|
|
@ -101,6 +101,107 @@ To learn more about lifecycle methods, [see the lifecycle methods page](lifecycl
|
|||
|
||||
---
|
||||
|
||||
### Alternate component syntaxes
|
||||
|
||||
#### ES6 classes
|
||||
|
||||
Components can also be written using ES6 class syntax:
|
||||
|
||||
```javascript
|
||||
class ES6ClassComponent {
|
||||
constructor(vnode) {
|
||||
// vnode.state is undefined at this point
|
||||
this.kind = "ES6 class"
|
||||
}
|
||||
view() {
|
||||
return m("div", `Hello from an ${this.kind}`)
|
||||
}
|
||||
oncreate() {
|
||||
console.log(`A ${this.kind} component was created`)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Component classes must define a `view()` method, detected via `.prototype.view`, to get the tree to render.
|
||||
|
||||
They can be consumed in the same way regular components can.
|
||||
|
||||
```javascript
|
||||
// EXAMPLE: via m.render
|
||||
m.render(document.body, m(ES6ClassComponent))
|
||||
|
||||
// EXAMPLE: via m.mount
|
||||
m.mount(document.body, ES6ClassComponent)
|
||||
|
||||
// EXAMPLE: via m.route
|
||||
m.route(document.body, "/", {
|
||||
"/": ES6ClassComponent
|
||||
})
|
||||
|
||||
// EXAMPLE: component composition
|
||||
class AnotherES6ClassComponent {
|
||||
view() {
|
||||
return m("main", [
|
||||
m(ES6ClassComponent)
|
||||
])
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Closure components
|
||||
|
||||
Functionally minded developers may prefer using the "closure component" syntax:
|
||||
|
||||
```javascript
|
||||
function closureComponent(vnode) {
|
||||
// vnode.state is undefined at this point
|
||||
var kind = "closure component"
|
||||
|
||||
return {
|
||||
view: function() {
|
||||
return m("div", "Hello from a " + kind)
|
||||
},
|
||||
oncreate: function() {
|
||||
console.log("We've created a " + kind)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The returned object must hold a `view` function, used to get the tree to render.
|
||||
|
||||
They can be consumed in the same way regular components can.
|
||||
|
||||
```javascript
|
||||
// EXAMPLE: via m.render
|
||||
m.render(document.body, m(closureComponent))
|
||||
|
||||
// EXAMPLE: via m.mount
|
||||
m.mount(document.body, closuresComponent)
|
||||
|
||||
// EXAMPLE: via m.route
|
||||
m.route(document.body, "/", {
|
||||
"/": closureComponent
|
||||
})
|
||||
|
||||
// EXAMPLE: component composition
|
||||
function anotherClosureComponent() {
|
||||
return {
|
||||
view: function() {
|
||||
return m("main", [
|
||||
m(closureComponent)
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Mixing component kinds
|
||||
|
||||
Components can be freely mixed. A Class component can have closure or POJO components as children, etc...
|
||||
|
||||
---
|
||||
|
||||
### State
|
||||
|
||||
Like all virtual DOM nodes, component vnodes can have state. Component state is useful for supporting object-oriented architectures, for encapsulation and for separation of concerns.
|
||||
|
|
@ -109,7 +210,7 @@ The state of a component can be accessed three ways: as a blueprint at initializ
|
|||
|
||||
#### At initialization
|
||||
|
||||
The component object is the prototype of each component instance, so any property defined on the component object will be accessible as a property of `vnode.state`. This allows simple state initialization.
|
||||
For POJO components, the component object is the prototype of each component instance, so any property defined on the component object will be accessible as a property of `vnode.state`. This allows simple state initialization.
|
||||
|
||||
In the example below, `data` is a property of the `ComponentWithInitialState` component's state object.
|
||||
|
||||
|
|
@ -127,6 +228,10 @@ m(ComponentWithInitialState)
|
|||
// <div>Initial content</div>
|
||||
```
|
||||
|
||||
For class components, the state is an instance of the class, set right after the constructor is called.
|
||||
|
||||
For closure components, the state is the object returned by the closure, set right after the closure returns. The state object is mostly redundant for closure components (since variables defined in the closure scope can be used instead).
|
||||
|
||||
#### Via vnode.state
|
||||
|
||||
State can also be accessed via the `vnode.state` property, which is available to all lifecycle methods as well as the `view` method of a component.
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ React | Mithril
|
|||
|
||||
Library load times matter in applications that don't stay open for long periods of time (for example, anything in mobile) and cannot be improved via caching or other optimization techniques.
|
||||
|
||||
Since this is a micro-benchmark, you are encourage to replicate these tests yourself since hardware can heavily affect the numbers. Note that bundler frameworks like Webpack can move dependencies out before the timer calls to emulate static module resolution, so you should either copy the code from the compiled CDN files or open the output file from the bundler library, and manually add the high resolution timer calls `console.time` and `console.timeEnd` to the bundled script. Avoid using `new Date` and `performance.now`, as those mechanisms are not as statistically accurate.
|
||||
Since this is a micro-benchmark, you are encouraged to replicate these tests yourself since hardware can heavily affect the numbers. Note that bundler frameworks like Webpack can move dependencies out before the timer calls to emulate static module resolution, so you should either copy the code from the compiled CDN files or open the output file from the bundler library, and manually add the high resolution timer calls `console.time` and `console.timeEnd` to the bundled script. Avoid using `new Date` and `performance.now`, as those mechanisms are not as statistically accurate.
|
||||
|
||||
For your reading convenience, here's a version of that benchmark adapted to use CDNs on the web: the [benchmark for React is here](https://jsfiddle.net/0ovkv64u/), and the [benchmark for Mithril is here](https://jsfiddle.net/o7hxooqL/). Note that we're benchmarking all of Mithril rather than benchmarking only the rendering module (which would be equivalent in scope to React). Also note that this CDN-driven setup incurs some overheads due to fetching resources from disk cache (~2ms per resource). Due to those reasons, the numbers here are not entirely accurate, but they should be sufficient to observe that Mithril's initialization speed is noticeably better than React.
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
- [Static members](#static-members)
|
||||
- [Stream.combine](#streamcombine)
|
||||
- [Stream.merge](#streammerge)
|
||||
- [Stream.scan](#streamscan)
|
||||
- [Stream.scanMerge](#streamscanmerge)
|
||||
- [Stream.HALT](#streamhalt)
|
||||
- [Stream["fantasy-land/of"]](#streamfantasy-landof)
|
||||
- [Instance members](#static-members)
|
||||
|
|
@ -114,6 +116,39 @@ Argument | Type | Required | Description
|
|||
|
||||
---
|
||||
|
||||
##### Stream.scan
|
||||
|
||||
Creates a new stream with the results of calling the function on every value in the stream with an accumulator and the incoming value.
|
||||
|
||||
`stream = Stream.scan(fn, accumulator, stream)`
|
||||
|
||||
Argument | Type | Required | Description
|
||||
------------- | -------------------------------- | -------- | ---
|
||||
`fn` | `(accumulator, value) -> result` | Yes | A function that takes an accumulator and value parameter and returns a new accumulator value
|
||||
`accumulator` | `any` | Yes | The starting value for the accumulator
|
||||
`stream` | `Stream` | Yes | Stream containing the values
|
||||
**returns** | `Stream` | | Returns a new stream containing the result
|
||||
|
||||
[How to read signatures](signatures.md)
|
||||
|
||||
---
|
||||
|
||||
##### Stream.scanMerge
|
||||
|
||||
Takes an array of pairs of streams and scan functions and merges all those streams using the given functions into a single stream.
|
||||
|
||||
`stream = Stream.scanMerge(pairs, accumulator)`
|
||||
|
||||
Argument | Type | Required | Description
|
||||
------------- | ------------------------------------------------ | -------- | ---
|
||||
`pairs` | `Array<[Stream, (accumulator, value) -> value]>` | Yes | An array of tuples of stream and scan functions
|
||||
`accumulator` | `any` | Yes | The starting value for the accumulator
|
||||
**returns** | `Stream` | | Returns a new stream containing the result
|
||||
|
||||
[How to read signatures](signatures.md)
|
||||
|
||||
---
|
||||
|
||||
##### Stream.HALT
|
||||
|
||||
A special value that can be returned to stream callbacks to halt execution of downstreams
|
||||
|
|
|
|||
|
|
@ -73,10 +73,11 @@ Property | Type | Description
|
|||
`text` | `(String|Number|Boolean)?` | This is used instead of `children` if a vnode contains a text node as its only child. This is done for performance reasons. Component vnodes never use the `text` property even if they have a text node as their only child.
|
||||
`dom` | `Element?` | Points to the element that corresponds to the vnode. This property is `undefined` in the `oninit` lifecycle method. In fragments and trusted HTML vnodes, `dom` points to the first element in the range.
|
||||
`domSize` | `Number?` | This is only set in fragment and trusted HTML vnodes, and it's `undefined` in all other vnode types. It defines the number of DOM elements that the vnode represents (starting from the element referenced by the `dom` property).
|
||||
`state` | `Object`? | An object that is persisted between redraws. It is provided by the core engine when needed. In component vnodes, the `state` inherits prototypically from the component object/class.
|
||||
`events` | `Object?` | An object that is persisted between redraws and that stores event handlers so that they can be removed using the DOM API. The `events` property is `undefined` if there are no event handlers defined. This property is only used internally by Mithril, do not use it.
|
||||
|
||||
|
||||
`state` | `Object?` | An object that is persisted between redraws. It is provided by the core engine when needed. In POJO component vnodes, the `state` inherits prototypically from the component object/class. In class component vnodes it is an instance of the class. In closure components it is the object returned by the closure.
|
||||
`_state` | `Object?` | For components, a reference to the original `vnode.state` object, used to lookup the `view` and hooks. This property is only used internally by Mithril, do not use or modify it.
|
||||
`events` | `Object?` | An object that is persisted between redraws and that stores event handlers so that they can be removed using the DOM API. The `events` property is `undefined` if there are no event handlers defined. This property is only used internally by Mithril, do not use or modify it.
|
||||
`instance` | `Object?` | For components, a storage location for the value returned by the `view`. This property is only used internally by Mithril, do not use or modify it.
|
||||
`skip` | `Boolean` | This property is only used internally by Mithril when diffing keyed lists, do not use or modify it.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -87,7 +88,7 @@ The `tag` property of a vnode determines its type. There are five vnode types:
|
|||
Vnode type | Example | Description
|
||||
------------ | ------------------------------ | ---
|
||||
Element | `{tag: "div"}` | Represents a DOM element.
|
||||
Fragment | `{tag: "[", children: []}` | Represents a list of DOM elements whose parent DOM element may also contain other elements that are not in the fragment. When using the [`m()`](hyperscript.md) helper function, fragment vnodes can only be created by nesting arrays into the `children` parameter of `m()`. `m("[")` does not create a valid vnode.
|
||||
Fragment | `{tag: "[", children: []}` | Represents a list of DOM elements whose parent DOM element may also contain other elements that are not in the fragment. When using the [`m()`](hyperscript.md) helper function, fragment vnodes can only be created by nesting arrays into the `children` parameter of `m()`. `m("[")` does not create a valid vnode.
|
||||
Text | `{tag: "#", children: ""}` | Represents a DOM text node.
|
||||
Trusted HTML | `{tag: "<", children: "<br>"}` | Represents a list of DOM elements from an HTML string.
|
||||
Component | `{tag: ExampleComponent}` | If `tag` is a Javascript object with a `view` method, the vnode represents the DOM generated by rendering the component.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue