-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
/
render.js
73 lines (66 loc) · 2.35 KB
/
render.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import { EMPTY_OBJ } from './constants';
import { commitRoot, diff } from './diff/index';
import { createElement, Fragment } from './create-element';
import options from './options';
import { slice } from './util';
/**
* Render a Preact virtual node into a DOM element
* @param {ComponentChild} vnode The virtual node to render
* @param {PreactElement} parentDom The DOM element to render into
* @param {PreactElement | object} [replaceNode] Optional: Attempt to re-use an
* existing DOM tree rooted at `replaceNode`
*/
export function render(vnode, parentDom, replaceNode) {
if (options._root) options._root(vnode, parentDom);
// We abuse the `replaceNode` parameter in `hydrate()` to signal if we are in
// hydration mode or not by passing the `hydrate` function instead of a DOM
// element..
let isHydrating = typeof replaceNode == 'function';
// To be able to support calling `render()` multiple times on the same
// DOM node, we need to obtain a reference to the previous tree. We do
// this by assigning a new `_children` property to DOM nodes which points
// to the last rendered tree. By default this property is not present, which
// means that we are mounting a new tree for the first time.
let oldVNode = isHydrating
? null
: (replaceNode && replaceNode._children) || parentDom._children;
vnode = ((!isHydrating && replaceNode) || parentDom)._children =
createElement(Fragment, null, [vnode]);
// List of effects that need to be called after diffing.
let commitQueue = [],
refQueue = [];
diff(
parentDom,
// Determine the new vnode tree and store it on the DOM element on
// our custom `_children` property.
vnode,
oldVNode || EMPTY_OBJ,
EMPTY_OBJ,
parentDom.ownerSVGElement !== undefined,
!isHydrating && replaceNode
? [replaceNode]
: oldVNode
? null
: parentDom.firstChild
? slice.call(parentDom.childNodes)
: null,
commitQueue,
!isHydrating && replaceNode
? replaceNode
: oldVNode
? oldVNode._dom
: parentDom.firstChild,
isHydrating,
refQueue
);
// Flush all queued effects
commitRoot(commitQueue, vnode, refQueue);
}
/**
* Update an existing DOM element with data from a Preact virtual node
* @param {ComponentChild} vnode The virtual node to render
* @param {PreactElement} parentDom The DOM element to update
*/
export function hydrate(vnode, parentDom) {
render(vnode, parentDom, hydrate);
}