Skip to content

Commit

Permalink
(feat) - replaceNode parameter (#1557)
Browse files Browse the repository at this point in the history
(feat) - replaceNode parameter
  • Loading branch information
marvinhagemeister authored Apr 22, 2019
2 parents 9edba30 + 37a8cd3 commit 3b7d356
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 2 deletions.
20 changes: 18 additions & 2 deletions src/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,30 @@ import options from './options';
* @param {import('./index').ComponentChild} vnode The virtual node to render
* @param {import('./internal').PreactElement} parentDom The DOM element to
* render into
* @param {import('./dom').PreactElement} [replaceNode] Attempt to re-use an
* existing DOM tree rooted at `replaceNode`
*/
export function render(vnode, parentDom) {
export function render(vnode, parentDom, replaceNode) {
if (options.root) options.root(vnode, parentDom);
let oldVNode = parentDom._prevVNode;
vnode = createElement(Fragment, null, [vnode]);

let mounts = [];
diffChildren(parentDom, parentDom._prevVNode = vnode, oldVNode, EMPTY_OBJ, parentDom.ownerSVGElement!==undefined, oldVNode ? null : EMPTY_ARR.slice.call(parentDom.childNodes), mounts, vnode, EMPTY_OBJ);
diffChildren(
parentDom,
replaceNode ? vnode : (parentDom._prevVNode = vnode),
replaceNode ? undefined : oldVNode,
EMPTY_OBJ,
parentDom.ownerSVGElement !== undefined,
replaceNode
? [replaceNode]
: oldVNode
? null
: EMPTY_ARR.slice.call(parentDom.childNodes),
mounts,
vnode,
replaceNode || EMPTY_OBJ
);
commitRoot(mounts, vnode);
}

Expand Down
40 changes: 40 additions & 0 deletions test/browser/render.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -966,4 +966,44 @@ describe('render()', () => {

expect(scratch.textContent).to.equal('01');
});

describe('replaceNode parameter', () => {

function appendChildToScratch(id) {
const child = document.createElement('div');
child.id = id;
scratch.appendChild(child);
}

beforeEach(() => {
['a', 'b', 'c'].forEach(id => appendChildToScratch(id));
});

it('should use replaceNode as render root and not inject into it', () => {
const childA = scratch.querySelector('#a');
render(<div id="a">contents</div>, scratch, childA);
expect(scratch.querySelector('#a')).to.equal(childA);
expect(childA.innerHTML).to.equal('contents');
});

it('should not remove siblings of replaceNode', () => {
const childA = scratch.querySelector('#a');
render(<div id="a" />, scratch, childA);
expect(scratch.innerHTML).to.equal('<div id="a"></div><div id="b"></div><div id="c"></div>');
});

it('should render multiple render roots in one parentDom', () => {
const childA = scratch.querySelector('#a');
const childB = scratch.querySelector('#b');
const childC = scratch.querySelector('#c');
const expectedA = '<div id="a">childA</div>';
const expectedB = '<div id="b">childB</div>';
const expectedC = '<div id="c">childC</div>';
render(<div id="a">childA</div>, scratch, childA);
render(<div id="b">childB</div>, scratch, childB);
render(<div id="c">childC</div>, scratch, childC);
expect(scratch.innerHTML).to.equal(`${expectedA}${expectedB}${expectedC}`);
});
});

});

0 comments on commit 3b7d356

Please sign in to comment.