add support for controller.prototype.onunload
This commit is contained in:
parent
762eeb7e31
commit
b23ffd1aee
7 changed files with 86 additions and 6 deletions
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
[v0.1.13](/mithril/archive/v0.1.13) - maintenance
|
||||
|
||||
### News:
|
||||
|
||||
- m.module now runs clean-up code in root module controllers that implement an `onunload` instance method [82](https://github.com/lhorie/mithril.js/issues/82)
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
- Removing CSS rules now diffs correctly [#79](https://github.com/lhorie/mithril.js/issues/79)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"version": "$version",
|
||||
"author": "Leo Horie <leohorie@hotmail.com>",
|
||||
"repository": {"type": "git", "url": "https://github.com/lhorie/mithril"},
|
||||
"main": "mithril.min.js",
|
||||
"main": "mithril.js",
|
||||
"licenses": [{"type": "MIT", "url": "http://opensource.org/licenses/MIT"}],
|
||||
"files": ["mithril.min.js", "mithril.min.map", "mithril.js"]
|
||||
}
|
||||
|
|
@ -103,6 +103,32 @@ yields:
|
|||
</body>
|
||||
```
|
||||
|
||||
### Unloading modules
|
||||
|
||||
If a module's controller implements an instance method called `onunload`, this method will be called when a new `m.module` call updates the root DOM element tied to the module in question.
|
||||
|
||||
```javascript
|
||||
var module1 = {};
|
||||
module1.controller = function() {
|
||||
this.onunload = function() {
|
||||
console.log("unloading module 1");
|
||||
};
|
||||
};
|
||||
module1.view = function() {};
|
||||
|
||||
m.module(document, module1);
|
||||
|
||||
|
||||
|
||||
var module2 = {};
|
||||
module2.controller = function() {};
|
||||
module1.view = function() {};
|
||||
|
||||
m.module(document, module2); // logs "unloading module 1"
|
||||
```
|
||||
|
||||
This mechanism is useful to clear timers and unsubscribe event handlers. If you have a hierarchy of components, you can recursively call `onunload` on all the components in the tree or use a [pubsub](http://microjs.com/#pubsub) library to unload specific components on demand.
|
||||
|
||||
---
|
||||
|
||||
### Signature
|
||||
|
|
@ -113,7 +139,8 @@ yields:
|
|||
void module(DOMElement rootElement, Module module)
|
||||
|
||||
where:
|
||||
Module :: Object { void controller(), void view(Object controllerInstance) }
|
||||
Module :: Object { Controller, void view(Object controllerInstance) }
|
||||
Controller :: void controller() | void controller() { prototype: void unload() }
|
||||
```
|
||||
|
||||
- **DOMElement rootElement**
|
||||
|
|
|
|||
|
|
@ -2,17 +2,17 @@
|
|||
|
||||
Redraws the view for the currently active module. Use [`m.module()`](mithril.module) to activate a module.
|
||||
|
||||
This method is called internally by Mithril's auto-redrawing system and is only documented for completeness; usually you should avoid calling it manually unless you explicitly want a multi-pass redraw cycle. One case where `m.redraw` may be useful is to force a manual redraw after background requests (see the `background` option in [`m.request`](mithril.request.md).
|
||||
|
||||
A multi-pass redraw cycle is usually only useful if you need non-trivial UI metrics measurements. A multi-pass cycle may span multiple browser repaints and therefore could cause flash of unbehaviored content (FOUC) and performance degradation.
|
||||
This method is called internally by Mithril's auto-redrawing system. Usually you don't need to call it manually unless you are doing recurring asynchronous operations (i.e. using `setInterval`) or if you want to decouple slow running background requests from the rendering context (see the `background` option in [`m.request`](mithril.request.md).
|
||||
|
||||
By default, if you're using either [`m.route`](mithril.route.md) or [`m.module`](mithril.module.md), `m.redraw()` is called automatically by Mithril's auto-redrawing system once the controller finishes executing.
|
||||
|
||||
`m.redraw` is also called automatically on event handlers defined in virtual elements.
|
||||
|
||||
Note that calling this method will not do anything if a module was not activated via either [`m.module()`](mithril.module) or [`m.route()`](mithril.route). This means that `m.redraw` doesn't do anything when instantiating controllers and rendering views via `m.render` manually.
|
||||
|
||||
If there are pending [`m.request`](mithril.request.md) calls in either a controller constructor or event handler, the auto-redrawing system waits for all the AJAX requests to complete before calling `m.redraw`.
|
||||
|
||||
This method may also be called manually from within a controller if more granular updates to the view are needed, however doing so is generally not recommended, as it may degrade performance. Model classes should never call this method.
|
||||
This method may also be called manually from within a controller if more granular updates to the view are needed, however doing so is generally not recommended, as it may degrade performance. Model classes should never call this method.
|
||||
|
||||
If you are developing an asynchronous model-level service and finding that Mithril is not redrawing the view after your code runs, you should use [`m.startComputation` and `m.endComputation`](mithril.computation.md) to integrate with Mithril's auto-redrawing system instead.
|
||||
|
||||
|
|
|
|||
|
|
@ -107,6 +107,34 @@ m.route.param("date") === "archive/2014"
|
|||
//the routes should be flipped around to get `m.route.param("year") == "2014"`
|
||||
```
|
||||
|
||||
### Running clean up code on route change
|
||||
|
||||
If a module's controller implements an instance method called `onunload`, this method will be called when a route changes.
|
||||
|
||||
```javascript
|
||||
var home = {};
|
||||
home.controller = function() {
|
||||
this.onunload = function() {
|
||||
console.log("unloading home module");
|
||||
};
|
||||
};
|
||||
|
||||
var dashboard = {};
|
||||
dashboard.controller = function() {};
|
||||
dashboard.view = function() {};
|
||||
|
||||
//go to the default route (home)
|
||||
m.route(document.body, "/", {
|
||||
"/": home,
|
||||
"/dashboard": dashboard,
|
||||
});
|
||||
|
||||
//re-route to dashboard
|
||||
m.route("/dashboard"); // logs "unloading home"
|
||||
```
|
||||
|
||||
This mechanism is useful to clear timers and unsubscribe event handlers. If you have a hierarchy of components, you can recursively call `unload` on all the components in the tree or use a [pubsub](http://microjs.com/#pubsub) library to unload specific components on demand.
|
||||
|
||||
---
|
||||
|
||||
#### Signature
|
||||
|
|
|
|||
|
|
@ -222,6 +222,7 @@ Mithril = m = new function app(window) {
|
|||
if (index < 0) index = roots.length
|
||||
roots[index] = root
|
||||
modules[index] = module
|
||||
if (controllers[index] && typeof controllers[index].onunload == "function") controllers[index].onunload()
|
||||
controllers[index] = new module.controller
|
||||
m.endComputation()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -345,6 +345,7 @@ function testMithril(mock) {
|
|||
return valueBefore1 === "UL" && valueAfter1 === "" && valueBefore2 === "" && valueAfter2 === "UL"
|
||||
})
|
||||
test(function() {
|
||||
//https://github.com/lhorie/mithril.js/issues/79
|
||||
var root = mock.document.createElement("div")
|
||||
m.render(root, m("div", {style: {background: "red"}}))
|
||||
var valueBefore = root.childNodes[0].style.background
|
||||
|
|
@ -357,6 +358,25 @@ function testMithril(mock) {
|
|||
m.render(root, m("div[style='background:red']"))
|
||||
return root.childNodes[0].style === "background:red"
|
||||
})
|
||||
test(function() {
|
||||
var root = mock.document.createElement("div")
|
||||
m.render(root, m("div", {style: {background: "red"}}))
|
||||
var valueBefore = root.childNodes[0].style.background
|
||||
m.render(root, m("div", {}))
|
||||
var valueAfter = root.childNodes[0].style.background
|
||||
return valueBefore === "red" && valueAfter === undefined
|
||||
})
|
||||
test(function() {
|
||||
var root = mock.document.createElement("div")
|
||||
var module = {}, unloaded = false
|
||||
module.controller = function() {
|
||||
this.onunload = function() {unloaded = true}
|
||||
}
|
||||
module.view = function() {}
|
||||
m.module(root, module)
|
||||
m.module(root, {controller: function() {}, view: function() {}})
|
||||
return unloaded === true
|
||||
})
|
||||
//end m.render
|
||||
|
||||
//m.redraw
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue