Skip to content

Commit 142e991

Browse files
committed
Add 'docs/' from commit '782e99d88000922cbe5cdd55f34566404c5a1777'
git-subtree-dir: docs git-subtree-mainline: b3d8d47 git-subtree-split: 782e99d
2 parents b3d8d47 + 782e99d commit 142e991

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+10790
-0
lines changed

docs/16.png

1.54 KB
Loading

docs/32.png

4.14 KB
Loading

docs/48.png

8.1 KB
Loading

docs/CNAME

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
mithril.js.org

docs/animation.md

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<!--meta-description
2+
Approaches you can use to animate your Mithril.js-based apps, including technology and performance suggestions
3+
-->
4+
5+
# Animations
6+
7+
- [Technology choices](#technology-choices)
8+
- [Animation on element creation](#animation-on-element-creation)
9+
- [Animation on element removal](#animation-on-element-removal)
10+
- [Performance](#performance)
11+
12+
---
13+
14+
### Technology choices
15+
16+
Animations are often used to make applications come alive. Nowadays, browsers have good support for CSS animations, and there are [various](https://greensock.com/gsap) [libraries](https://github.com/julianshapiro/velocity) that provide fast JavaScript-based animations. There's also an upcoming [Web API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Using_the_Web_Animations_API) and a [polyfill](https://github.com/web-animations/web-animations-js) if you like living on the bleeding edge.
17+
18+
Mithril.js does not provide any animation APIs per se, since these other options are more than sufficient to achieve rich, complex animations. Mithril.js does, however, offer hooks to make life easier in some specific cases where it's traditionally difficult to make animations work.
19+
20+
---
21+
22+
### Animation on element creation
23+
24+
Animating an element via CSS when the element is created couldn't be simpler. Just add an animation to a CSS class normally:
25+
26+
```css
27+
.fancy {animation:fade-in 0.5s;}
28+
@keyframes fade-in {
29+
from {opacity:0;}
30+
to {opacity:1;}
31+
}
32+
```
33+
34+
```javascript
35+
var FancyComponent = {
36+
view: function() {
37+
return m(".fancy", "Hello world")
38+
}
39+
}
40+
41+
m.mount(document.body, FancyComponent)
42+
```
43+
44+
---
45+
46+
### Animation on element removal
47+
48+
The problem with animating before removing an element is that we must wait until the animation is complete before we can actually remove the element. Fortunately, Mithril.js offers the [`onbeforeremove`](lifecycle-methods.md#onbeforeremove) hook that allows us to defer the removal of an element.
49+
50+
Let's create an `exit` animation that fades `opacity` from 1 to 0.
51+
52+
```css
53+
.exit {animation:fade-out 0.5s;}
54+
@keyframes fade-out {
55+
from {opacity:1;}
56+
to {opacity:0;}
57+
}
58+
```
59+
60+
Now let's create a contrived component that shows and hides the `FancyComponent` we created in the previous section:
61+
62+
```javascript
63+
var on = true
64+
65+
var Toggler = {
66+
view: function() {
67+
return [
68+
m("button", {onclick: function() {on = !on}}, "Toggle"),
69+
on ? m(FancyComponent) : null,
70+
]
71+
}
72+
}
73+
```
74+
75+
Next, let's modify `FancyComponent` so that it fades out when removed:
76+
77+
```javascript
78+
var FancyComponent = {
79+
onbeforeremove: function(vnode) {
80+
vnode.dom.classList.add("exit")
81+
return new Promise(function(resolve) {
82+
vnode.dom.addEventListener("animationend", resolve)
83+
})
84+
},
85+
view: function() {
86+
return m(".fancy", "Hello world")
87+
}
88+
}
89+
```
90+
91+
`vnode.dom` points to the root DOM element of the component (`<div class="fancy">`). We use the classList API here to add an `exit` class to `<div class="fancy">`.
92+
93+
Then we return a Promise that resolves when the `animationend` event fires. When we return a promise from `onbeforeremove`, Mithril.js waits until the promise is resolved and only then it removes the element. In this case, it waits for the exit animation to finish.
94+
95+
We can verify that both the enter and exit animations work by mounting the `Toggler` component:
96+
97+
```javascript
98+
m.mount(document.body, Toggler)
99+
```
100+
101+
Note that the `onbeforeremove` hook only fires on the element that loses its `parentNode` when an element gets detached from the DOM. This behavior is by design and exists to prevent a potential jarring user experience where every conceivable exit animation on the page would run on a route change. If your exit animation is not running, make sure to attach the `onbeforeremove` handler as high up the tree as it makes sense to ensure that your animation code is called.
102+
103+
---
104+
105+
### Performance
106+
107+
When creating animations, it's recommended that you only use the `opacity` and `transform` CSS rules, since these can be hardware-accelerated by modern browsers and yield better performance than animating `top`, `left`, `width`, and `height`.
108+
109+
It's also recommended that you avoid the `box-shadow` rule and selectors like `:nth-child`, since these are also resource intensive options. If you want to animate a `box-shadow`, consider [putting the `box-shadow` rule on a pseudo element, and animate that element's opacity instead](https://tobiasahlin.com/blog/how-to-animate-box-shadow/). Other things that can be expensive include large or dynamically scaled images and overlapping elements with different `position` values (e.g. an absolute positioned element over a fixed element).

docs/api.md

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
<!--meta-description
2+
An API cheatsheet for Mithril.js
3+
-->
4+
5+
# API
6+
7+
### Cheatsheet
8+
9+
Here are examples for the most commonly used methods. If a method is not listed below, it's meant for advanced usage.
10+
11+
#### m(selector, attrs, children) - [docs](hyperscript.md)
12+
13+
```javascript
14+
m("div.class#id", {title: "title"}, ["children"])
15+
```
16+
17+
---
18+
19+
#### m.mount(element, component) - [docs](mount.md)
20+
21+
```javascript
22+
var state = {
23+
count: 0,
24+
inc: function() {state.count++}
25+
}
26+
27+
var Counter = {
28+
view: function() {
29+
return m("div", {onclick: state.inc}, state.count)
30+
}
31+
}
32+
33+
m.mount(document.body, Counter)
34+
```
35+
36+
---
37+
38+
#### m.route(root, defaultRoute, routes) - [docs](route.md)
39+
40+
```javascript
41+
var Home = {
42+
view: function() {
43+
return "Welcome"
44+
}
45+
}
46+
47+
m.route(document.body, "/home", {
48+
"/home": Home, // defines `https://example.com/#!/home`
49+
})
50+
```
51+
52+
#### m.route.set(path) - [docs](route.md#mrouteset)
53+
54+
```javascript
55+
m.route.set("/home")
56+
```
57+
58+
#### m.route.get() - [docs](route.md#mrouteget)
59+
60+
```javascript
61+
var currentRoute = m.route.get()
62+
```
63+
64+
#### m.route.prefix = prefix - [docs](route.md#mrouteprefix)
65+
66+
Invoke this before `m.route()` to change the routing prefix.
67+
68+
```javascript
69+
m.route.prefix = "#!"
70+
```
71+
72+
#### m(m.route.Link, ...) - [docs](route.md#mroutelink)
73+
74+
```javascript
75+
m(m.route.Link, {href: "/Home"}, "Go to home page")
76+
```
77+
78+
---
79+
80+
#### m.request(options) - [docs](request.md)
81+
82+
```javascript
83+
m.request({
84+
method: "PUT",
85+
url: "/api/v1/users/:id",
86+
params: {id: 1, name: "test"}
87+
})
88+
.then(function(result) {
89+
console.log(result)
90+
})
91+
```
92+
93+
---
94+
95+
#### m.parseQueryString(querystring) - [docs](parseQueryString.md)
96+
97+
```javascript
98+
var object = m.parseQueryString("a=1&b=2")
99+
// {a: "1", b: "2"}
100+
```
101+
102+
---
103+
104+
#### m.buildQueryString(object) - [docs](buildQueryString.md)
105+
106+
```javascript
107+
var querystring = m.buildQueryString({a: "1", b: "2"})
108+
// "a=1&b=2"
109+
```
110+
111+
---
112+
113+
#### m.trust(htmlString) - [docs](trust.md)
114+
115+
```javascript
116+
m.render(document.body, m.trust("<h1>Hello</h1>"))
117+
```
118+
119+
---
120+
121+
#### m.redraw() - [docs](redraw.md)
122+
123+
```javascript
124+
var count = 0
125+
function inc() {
126+
setInterval(function() {
127+
count++
128+
m.redraw()
129+
}, 1000)
130+
}
131+
132+
var Counter = {
133+
oninit: inc,
134+
view: function() {
135+
return m("div", count)
136+
}
137+
}
138+
139+
m.mount(document.body, Counter)
140+
```

docs/autoredraw.md

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
<!--meta-description
2+
The Mithril.js auto-redraw system re-renders your app after some functions complete. Here, we describe the idiomatic Mithril.js patterns that trigger those redraws.
3+
-->
4+
5+
# The auto-redraw system
6+
7+
Mithril.js implements a virtual DOM diffing system for fast rendering, and in addition, it offers various mechanisms to gain granular control over the rendering of an application.
8+
9+
When used idiomatically, Mithril.js employs an auto-redraw system that synchronizes the DOM whenever changes are made in the data layer. The auto-redraw system becomes enabled when you call `m.mount` or `m.route` (but it stays disabled if your app is bootstrapped solely via `m.render` calls).
10+
11+
The auto-redraw system simply consists of triggering a re-render function behind the scenes after certain functions complete.
12+
13+
### After event handlers
14+
15+
Mithril.js automatically redraws after DOM event handlers that are defined in a Mithril.js view:
16+
17+
```javascript
18+
var MyComponent = {
19+
view: function() {
20+
return m("div", {onclick: doSomething})
21+
}
22+
}
23+
24+
function doSomething() {
25+
// a redraw happens synchronously after this function runs
26+
}
27+
28+
m.mount(document.body, MyComponent)
29+
```
30+
31+
You can disable an auto-redraw for specific events by setting `e.redraw` to `false`.
32+
33+
```javascript
34+
var MyComponent = {
35+
view: function() {
36+
return m("div", {onclick: doSomething})
37+
}
38+
}
39+
40+
function doSomething(e) {
41+
e.redraw = false
42+
// no longer triggers a redraw when the div is clicked
43+
}
44+
45+
m.mount(document.body, MyComponent)
46+
```
47+
48+
49+
### After m.request
50+
51+
Mithril.js automatically redraws after [`m.request`](request.md) completes:
52+
53+
```javascript
54+
m.request("/api/v1/users").then(function() {
55+
// a redraw happens after this function runs
56+
})
57+
```
58+
59+
You can disable an auto-redraw for a specific request by setting the `background` option to true:
60+
61+
```javascript
62+
m.request("/api/v1/users", {background: true}).then(function() {
63+
// does not trigger a redraw
64+
})
65+
```
66+
67+
68+
### After route changes
69+
70+
Mithril.js automatically redraws after [`m.route.set()`](route.md#mrouteset) calls and after route changes via links using [`m.route.Link`](route.md#mroutelink).
71+
72+
```javascript
73+
var RoutedComponent = {
74+
view: function() {
75+
return [
76+
// a redraw happens asynchronously after the route changes
77+
m(m.route.Link, {href: "/"}),
78+
m("div", {
79+
onclick: function() {
80+
m.route.set("/")
81+
}
82+
}),
83+
]
84+
}
85+
}
86+
87+
m.route(document.body, "/", {
88+
"/": RoutedComponent,
89+
})
90+
```
91+
92+
---
93+
94+
### When Mithril.js does not redraw
95+
96+
Mithril.js does not redraw after `setTimeout`, `setInterval`, `requestAnimationFrame`, raw `Promise` resolutions and 3rd party library event handlers (e.g. Socket.io callbacks). In those cases, you must manually call [`m.redraw()`](redraw.md).
97+
98+
Mithril.js also does not redraw after lifecycle methods. Parts of the UI may be redrawn after an `oninit` handler, but other parts of the UI may already have been redrawn when a given `oninit` handler fires. Handlers like `oncreate` and `onupdate` fire after the UI has been redrawn.
99+
100+
If you need to explicitly trigger a redraw within a lifecycle method, you should call `m.redraw()`, which will trigger an asynchronous redraw.
101+
102+
```javascript
103+
function StableComponent() {
104+
var height = 0
105+
106+
return {
107+
oncreate: function(vnode) {
108+
height = vnode.dom.offsetHeight
109+
m.redraw()
110+
},
111+
view: function() {
112+
return m("div", "This component is " + height + "px tall")
113+
}
114+
}
115+
}
116+
```
117+
118+
Mithril.js does not auto-redraw vnode trees that are rendered via `m.render`. This means redraws do not occur after event changes and `m.request` calls for templates that were rendered via `m.render`. Thus, if your architecture requires manual control over when rendering occurs (as can sometimes be the case when using libraries like Redux), you should use `m.render` instead of `m.mount`.
119+
120+
Remember that `m.render` expects a vnode tree, and `m.mount` expects a component:
121+
122+
```javascript
123+
// wrap the component in a m() call for m.render
124+
m.render(document.body, m(MyComponent))
125+
126+
// don't wrap the component for m.mount
127+
m.mount(document.body, MyComponent)
128+
```
129+
130+
Mithril.js may also avoid auto-redrawing if the frequency of requested redraws is higher than one animation frame (typically around 16ms). This means, for example, that when using fast-firing events like `onresize` or `onscroll`, Mithril.js will automatically throttle the number of redraws to avoid lag.

0 commit comments

Comments
 (0)