document flag
This commit is contained in:
parent
1a57bcc403
commit
71a19a27a9
3 changed files with 120 additions and 16 deletions
|
|
@ -8,6 +8,7 @@
|
|||
- [Accessing the real DOM element](#accessing-the-real-dom-element)
|
||||
- [Persisting config data](#persisting-config-data)
|
||||
- [Destructors](#destructors)
|
||||
- [Persising DOM elements across route changes](#persising-dom-elements-across-route-changes)
|
||||
- [SVG](#svg)
|
||||
- [Dealing with focus](#dealing-with-focus)
|
||||
- [Dealing with sorting and deleting in lists](#dealing-with-sorting-and-deleting-in-lists)
|
||||
|
|
@ -342,6 +343,67 @@ m.render(document, m("a")); //logs `unloaded the div` and `alert` never gets cal
|
|||
|
||||
---
|
||||
|
||||
#### Persising DOM elements across route changes
|
||||
|
||||
When using the [router](mithril.route.md), a route change recreates the DOM tree from scratch in order to unload plugins from the previous page. If you want to keep a DOM element intact across a route change, you can set the `retain` flag in the config's context object.
|
||||
|
||||
In the example below, there are two routes, each of which loads a module when a user navigates to their respective URLs. Both modules use a `menu` template, which contains links for navigation between the two modules, and an expensive-to-reinitialize element. Setting `context.retain = true` in the element's config function allows the span to stay intact after a route change.
|
||||
|
||||
```javascript
|
||||
//a menu template
|
||||
var menu = function() {
|
||||
return m("div", [
|
||||
m("a[href='/']", {config: m.route}, "Home"),
|
||||
m("a[href='/contact']", {config: m.route}, "Contact"),
|
||||
//an expensive-to-initialize DOM element
|
||||
m("span", {config: persistent})
|
||||
])
|
||||
}
|
||||
//a configuration that persists across route changes
|
||||
function persistent(el, isInit, context) {
|
||||
context.retain = true
|
||||
|
||||
if (!isInit) {
|
||||
//only runs once, even if you move back and forth between `/` and `/contact`
|
||||
doSomethingExpensive(el)
|
||||
}
|
||||
}
|
||||
|
||||
//modules that use the menu above
|
||||
var Home = {
|
||||
controller: function() {},
|
||||
view: function() {
|
||||
return [
|
||||
menu(),
|
||||
m("h1", "Home")
|
||||
]
|
||||
}
|
||||
}
|
||||
var Contact = {
|
||||
view: function() {
|
||||
return [
|
||||
menu(),
|
||||
m("h2", "Contact")
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
m.route(document.body, "/", {
|
||||
"/": Home,
|
||||
"/contact": Contact
|
||||
})
|
||||
```
|
||||
|
||||
Note that even if you set `context.retain = true`, the element will still be destroyed and recreated if it is different enough from the existing element. An element is considered "different enough" if:
|
||||
|
||||
- the tag name changes, or
|
||||
- the list of HTML attributes changes, or
|
||||
- the value of the element's id attribute changes
|
||||
|
||||
In addition, setting `context.retain = false` will also cause the element to be recreated, even if it is not considered different enough.
|
||||
|
||||
---
|
||||
|
||||
#### SVG
|
||||
|
||||
You can use Mithril to create SVG documents (as long as you don't need to support browsers that don't support SVG natively).
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ var m = (function app(window, undefined) {
|
|||
//- this prevents lifecycle surprises from procedural helpers that mix implicit and explicit return statements (e.g. function foo() {if (cond) return m("div")}
|
||||
//- it simplifies diffing code
|
||||
//data.toString() is null if data is the return value of Console.log in Firefox
|
||||
if (data == null || data.toString() == null) data = "";
|
||||
try {if (data == null || data.toString() == null) data = "";} catch (e) {data = ""}
|
||||
if (data.subtree === "retain") return cached;
|
||||
var cachedType = type.call(cached), dataType = type.call(data);
|
||||
if (cached == null || cachedType !== dataType) {
|
||||
|
|
@ -120,7 +120,7 @@ var m = (function app(window, undefined) {
|
|||
len = data.length
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var nodes = [], intact = cached.length === data.length, subArrayCount = 0;
|
||||
|
||||
//keys algorithm: sort elements without recreating them if keys are present
|
||||
|
|
@ -238,7 +238,7 @@ var m = (function app(window, undefined) {
|
|||
var dataAttrKeys = Object.keys(data.attrs)
|
||||
var hasKeys = dataAttrKeys.length > ("key" in data.attrs ? 1 : 0)
|
||||
//if an element is different enough from the one in cache, recreate it
|
||||
if (data.tag != cached.tag || dataAttrKeys.join() != Object.keys(cached.attrs).join() || data.attrs.id != cached.attrs.id || (m.redraw.strategy() == "all" && cached.configContext && cached.configContext.reuse !== true) || (m.redraw.strategy() == "diff" && cached.configContext && cached.configContext.reuse === false)) {
|
||||
if (data.tag != cached.tag || dataAttrKeys.join() != Object.keys(cached.attrs).join() || data.attrs.id != cached.attrs.id || (m.redraw.strategy() == "all" && cached.configContext && cached.configContext.retain !== true) || (m.redraw.strategy() == "diff" && cached.configContext && cached.configContext.retain === false)) {
|
||||
if (cached.nodes.length) clear(cached.nodes);
|
||||
if (cached.configContext && typeof cached.configContext.onunload === FUNCTION) cached.configContext.onunload()
|
||||
}
|
||||
|
|
@ -274,7 +274,7 @@ var m = (function app(window, undefined) {
|
|||
}
|
||||
//schedule configs to be called. They are called after `build` finishes running
|
||||
if (typeof data.attrs["config"] === FUNCTION) {
|
||||
var context = cached.configContext = cached.configContext || {};
|
||||
var context = cached.configContext = cached.configContext || {retain: m.redraw.strategy() == "diff"};
|
||||
|
||||
// bind
|
||||
var callback = function(data, args) {
|
||||
|
|
|
|||
|
|
@ -1783,6 +1783,48 @@ function testMithril(mock) {
|
|||
mock.requestAnimationFrame.$resolve()
|
||||
mock.location.search = "?"
|
||||
|
||||
var root = mock.document.createElement("div")
|
||||
var value
|
||||
|
||||
var a = {}
|
||||
a.controller = function() {}
|
||||
a.view = function() {
|
||||
return m("a", {config: function(el, init, ctx) {
|
||||
value = ctx.retain
|
||||
}})
|
||||
}
|
||||
|
||||
m.route(root, "/a", {
|
||||
"/a": a
|
||||
})
|
||||
|
||||
return value === false
|
||||
})
|
||||
test(function() {
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
mock.location.search = "?"
|
||||
|
||||
var root = mock.document.createElement("div")
|
||||
var value
|
||||
|
||||
var a = {}
|
||||
a.controller = function() {m.redraw.strategy("diff")}
|
||||
a.view = function() {
|
||||
return m("a", {config: function(el, init, ctx) {
|
||||
value = ctx.retain
|
||||
}})
|
||||
}
|
||||
|
||||
m.route(root, "/a", {
|
||||
"/a": a
|
||||
})
|
||||
|
||||
return value === true
|
||||
})
|
||||
test(function() {
|
||||
mock.requestAnimationFrame.$resolve()
|
||||
mock.location.search = "?"
|
||||
|
||||
var root = mock.document.createElement("div")
|
||||
var initCount = 0
|
||||
|
||||
|
|
@ -1790,7 +1832,7 @@ function testMithril(mock) {
|
|||
a.controller = function() {}
|
||||
a.view = function() {
|
||||
return m("a", {config: function(el, init, ctx) {
|
||||
ctx.reuse = false
|
||||
ctx.retain = false
|
||||
if (!init) initCount++
|
||||
}})
|
||||
}
|
||||
|
|
@ -1822,7 +1864,7 @@ function testMithril(mock) {
|
|||
a.controller = function() {}
|
||||
a.view = function() {
|
||||
return m("a", {config: function(el, init, ctx) {
|
||||
ctx.reuse = true
|
||||
ctx.retain = true
|
||||
if (!init) initCount++
|
||||
}})
|
||||
}
|
||||
|
|
@ -1885,7 +1927,7 @@ function testMithril(mock) {
|
|||
a.controller = function() {m.redraw.strategy("diff")}
|
||||
a.view = function() {
|
||||
return m("a", {config: function(el, init, ctx) {
|
||||
ctx.reuse = true
|
||||
ctx.retain = true
|
||||
if (!init) initCount++
|
||||
}})
|
||||
}
|
||||
|
|
@ -1917,7 +1959,7 @@ function testMithril(mock) {
|
|||
a.controller = function() {m.redraw.strategy("diff")}
|
||||
a.view = function() {
|
||||
return m("a", {config: function(el, init, ctx) {
|
||||
ctx.reuse = false
|
||||
ctx.retain = false
|
||||
if (!init) initCount++
|
||||
}})
|
||||
}
|
||||
|
|
@ -1949,7 +1991,7 @@ function testMithril(mock) {
|
|||
a.controller = function() {}
|
||||
a.view = function() {
|
||||
return m("div", m("a", {config: function(el, init, ctx) {
|
||||
ctx.reuse = true
|
||||
ctx.retain = true
|
||||
if (!init) initCount++
|
||||
}}))
|
||||
}
|
||||
|
|
@ -1958,7 +2000,7 @@ function testMithril(mock) {
|
|||
b.controller = function() {}
|
||||
b.view = function() {
|
||||
return m("section", m("a", {config: function(el, init, ctx) {
|
||||
ctx.reuse = true
|
||||
ctx.retain = true
|
||||
if (!init) initCount++
|
||||
}}))
|
||||
}
|
||||
|
|
@ -1986,7 +2028,7 @@ function testMithril(mock) {
|
|||
a.controller = function() {}
|
||||
a.view = function() {
|
||||
return m("div", m("a", {config: function(el, init, ctx) {
|
||||
ctx.reuse = false
|
||||
ctx.retain = false
|
||||
if (!init) initCount++
|
||||
}}))
|
||||
}
|
||||
|
|
@ -1995,7 +2037,7 @@ function testMithril(mock) {
|
|||
b.controller = function() {}
|
||||
b.view = function() {
|
||||
return m("section", m("a", {config: function(el, init, ctx) {
|
||||
ctx.reuse = false
|
||||
ctx.retain = false
|
||||
if (!init) initCount++
|
||||
}}))
|
||||
}
|
||||
|
|
@ -2058,7 +2100,7 @@ function testMithril(mock) {
|
|||
a.controller = function() {m.redraw.strategy("diff")}
|
||||
a.view = function() {
|
||||
return m("div", m("a", {config: function(el, init, ctx) {
|
||||
ctx.reuse = true
|
||||
ctx.retain = true
|
||||
if (!init) initCount++
|
||||
}}))
|
||||
}
|
||||
|
|
@ -2067,7 +2109,7 @@ function testMithril(mock) {
|
|||
b.controller = function() {m.redraw.strategy("diff")}
|
||||
b.view = function() {
|
||||
return m("section", m("a", {config: function(el, init, ctx) {
|
||||
ctx.reuse = true
|
||||
ctx.retain = true
|
||||
if (!init) initCount++
|
||||
}}))
|
||||
}
|
||||
|
|
@ -2095,7 +2137,7 @@ function testMithril(mock) {
|
|||
a.controller = function() {m.redraw.strategy("diff")}
|
||||
a.view = function() {
|
||||
return m("div", m("a", {config: function(el, init, ctx) {
|
||||
ctx.reuse = false
|
||||
ctx.retain = false
|
||||
if (!init) initCount++
|
||||
}}))
|
||||
}
|
||||
|
|
@ -2104,7 +2146,7 @@ function testMithril(mock) {
|
|||
b.controller = function() {m.redraw.strategy("diff")}
|
||||
b.view = function() {
|
||||
return m("section", m("a", {config: function(el, init, ctx) {
|
||||
ctx.reuse = false
|
||||
ctx.retain = false
|
||||
if (!init) initCount++
|
||||
}}))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue