Support for skipping redraws (#1049)

Mostly useful for event handlers, setting `e.redraw = false` will prevent mithril from re-rendering.
This commit is contained in:
Pat Cavit 2016-05-20 11:50:41 -07:00
parent 2ca8fa6e66
commit 04eaa25ab1
4 changed files with 76 additions and 1 deletions

View file

@ -77,6 +77,38 @@ o.spec("m.mount", function() {
}, FRAME_BUDGET)
})
o("event handlers can skip redraw", function(done) {
var onupdate = o.spy()
var oninit = o.spy()
var mount = createMounter($window, {})
var e = $window.document.createEvent("MouseEvents")
e.initEvent("click", true, true)
mount(root, {
view: function() {
return m("div", {
oninit: oninit,
onupdate: onupdate,
onclick: function(e) {
e.redraw = false
}
})
}
})
root.firstChild.dispatchEvent(e)
o(oninit.callCount).equals(1)
// Wrapped to ensure no redraw fired
setTimeout(function() {
o(onupdate.callCount).equals(0)
done()
}, 20)
})
o("redraws on redraw.run()", function(done) {
var onupdate = o.spy()
var oninit = o.spy()

View file

@ -114,6 +114,40 @@ o.spec("m.route", function() {
}, FRAME_BUDGET)
})
o("event handlers can skip redraw", function(done) {
var onupdate = o.spy()
var oninit = o.spy()
var onclick = o.spy()
var e = $window.document.createEvent("MouseEvents")
e.initEvent("click", true, true)
route(root, "/", {
"/" : {
view: function() {
return m("div", {
oninit: oninit,
onupdate: onupdate,
onclick: function(e) {
e.redraw = false
},
})
}
}
})
root.firstChild.dispatchEvent(e)
o(oninit.callCount).equals(1)
// Wrapped to ensure no redraw fired
setTimeout(function() {
o(onupdate.callCount).equals(0)
done()
}, 20)
})
o("changes location on route.link", function() {
var e = $window.document.createEvent("MouseEvents")

View file

@ -81,4 +81,12 @@ o.spec("throttle", function() {
o(spy.callCount).equals(2)
})
})
o("it supports aborting when redraw is falsey", function() {
throttled({ redraw : false })
throttled({ redraw : 0 })
throttled({ redraw : "" })
o(spy.callCount).equals(0)
})
})

View file

@ -7,6 +7,7 @@ module.exports = function(callback) {
var timeout = typeof requestAnimationFrame === "function" ? requestAnimationFrame : setTimeout
return function(synchronous) {
var now = new Date().getTime()
if (typeof synchronous === "object" && "redraw" in synchronous && !synchronous.redraw) return
if (synchronous === true || last === 0 || now - last >= time) {
last = now
callback()