diff --git a/api/mount-redraw.js b/api/mount-redraw.js index 4f7d0f606..846f93d92 100644 --- a/api/mount-redraw.js +++ b/api/mount-redraw.js @@ -4,10 +4,33 @@ var Vnode = require("../render/vnode") module.exports = function(render, schedule, console) { var subscriptions = [] + var microSubscribers = new Map(); var pending = false var offset = -1 - function sync() { + + function reactive(component) { + function saveOldVdom() { + microSubscribers.set(component, this); + } + component.view = component.view.bind(component); + component.postupdate = saveOldVdom; + component.postcreate = saveOldVdom; + + return component; + } + + function sync(component) { + if(component){ + const oldComponent = microSubscribers.get(component); + if(oldComponent){ + const dom = oldComponent.dom.parentElement; + dom.vnodes = [oldComponent]; + try { render(dom, Vnode(component), redraw, oldComponent.dom.nextSibling) } + catch (e) { console.error(e) } + return; + } + } for (offset = 0; offset < subscriptions.length; offset += 2) { try { render(subscriptions[offset], Vnode(subscriptions[offset + 1]), redraw) } catch (e) { console.error(e) } @@ -15,12 +38,12 @@ module.exports = function(render, schedule, console) { offset = -1 } - function redraw() { + function redraw(component) { if (!pending) { pending = true schedule(function() { pending = false - sync() + sync(component) }) } } @@ -45,5 +68,5 @@ module.exports = function(render, schedule, console) { } } - return {mount: mount, redraw: redraw} + return {mount: mount, redraw: redraw, reactive: reactive} } diff --git a/index.js b/index.js index b6ca3406a..4a5a6baff 100644 --- a/index.js +++ b/index.js @@ -13,6 +13,7 @@ m.Fragment = "[" m.mount = mountRedraw.mount m.route = require("./route") m.render = require("./render") +m.reactive = mountRedraw.reactive m.redraw = mountRedraw.redraw m.request = request.request m.parseQueryString = require("./querystring/parse") diff --git a/reactive.js b/reactive.js new file mode 100644 index 000000000..15588ae40 --- /dev/null +++ b/reactive.js @@ -0,0 +1,3 @@ +"use strict" + +module.exports = require("./mount-redraw").reactive diff --git a/render/render.js b/render/render.js index d9b0f9d76..91e8e89d0 100644 --- a/render/render.js +++ b/render/render.js @@ -167,6 +167,8 @@ module.exports = function() { else { vnode.domSize = 0 } + // postcreate is called after the component is created + if(vnode.tag.postcreate) vnode.tag.postcreate.apply(vnode); } //update @@ -478,6 +480,8 @@ module.exports = function() { vnode.dom = old.dom vnode.domSize = old.domSize } + // postupdate is called after the component is updated + if(vnode.tag.postupdate) vnode.tag.postupdate.apply(vnode); } function getKeyMap(vnodes, start, end) { var map = Object.create(null) @@ -883,7 +887,7 @@ module.exports = function() { var currentDOM - return function(dom, vnodes, redraw) { + return function(dom, vnodes, redraw, nextSibling = null) { if (!dom) throw new TypeError("DOM element being rendered to does not exist.") if (currentDOM != null && dom.contains(currentDOM)) { throw new TypeError("Node is currently being rendered to and thus is locked.") @@ -901,7 +905,7 @@ module.exports = function() { // First time rendering into a node clears it out if (dom.vnodes == null) dom.textContent = "" vnodes = Vnode.normalizeChildren(Array.isArray(vnodes) ? vnodes : [vnodes]) - updateNodes(dom, dom.vnodes, vnodes, hooks, null, namespace === "http://www.w3.org/1999/xhtml" ? undefined : namespace) + updateNodes(dom, dom.vnodes, vnodes, hooks, nextSibling, namespace === "http://www.w3.org/1999/xhtml" ? undefined : namespace) dom.vnodes = vnodes // `document.activeElement` can return null: https://html.spec.whatwg.org/multipage/interaction.html#dom-document-activeelement if (active != null && activeElement(dom) !== active && typeof active.focus === "function") active.focus()