Skip to content
This repository has been archived by the owner on Aug 16, 2023. It is now read-only.

Commit

Permalink
feat: render api change
Browse files Browse the repository at this point in the history
  • Loading branch information
zeromake committed Aug 29, 2017
1 parent 3a96f81 commit 342efaa
Show file tree
Hide file tree
Showing 12 changed files with 58 additions and 55 deletions.
12 changes: 6 additions & 6 deletions src/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ let isScheduling = false;
* @param merge 原dom元素
* @param domChild 虚拟dom用于挂载原来挂载在dom元素上的属性
*/
export function render(vnode: IVNode, parent: Element, vdom: IVDom): IVDom {
export function render(vnode: IVNode, parent: Element, dom?: Element): IVDom {
const tmp: any = dom;
const vdom = tmp && tmp._vdom;
const newVDom = diff(vdom, vnode, {}, false, parent, false);
if (DEVTOOLS_ENV !== "production") {
if (!window.ZREACT_DEV && !isScheduling && typeof window.Map === "function") {
Expand All @@ -32,10 +34,8 @@ export function render(vnode: IVNode, parent: Element, vdom: IVDom): IVDom {
isScheduling = false;
});
}
} else if (ENV !== "production") {
const dom: any = newVDom.base;
dom._vdom = newVDom;
// window.$zreact = base;
}
return newVDom;
const base: any = newVDom.base;
// base._vdom = newVDom;
return base;
}
5 changes: 5 additions & 0 deletions src/vdom/diff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ function idiff(
const newVDom: IVDom = {
base: dom,
}; // new VDom(dom);

const tmp: any = dom;
tmp._vdom = newVDom;
if (vdom) {
// 来自renderComponent判断并处理vdom的子vdom更换
if (componentRoot) {
Expand Down Expand Up @@ -167,6 +170,8 @@ function idiff(
const newVDom: IVDom = {
base: out,
};
const tmp: any = out;
tmp._vdom = newVDom;
if (vdom) {
// 来自renderComponent判断并处理vdom的子vdom更换
if (componentRoot) {
Expand Down
File renamed without changes.
File renamed without changes.
48 changes: 24 additions & 24 deletions test/browser/devtools.js → test/browser/devtools.jsd
Original file line number Diff line number Diff line change
Expand Up @@ -98,66 +98,66 @@ describe_('React Developer Tools integration', () => {

it('notifies dev tools about component updates', () => {
const node = render(h(StatefulComponent), container);
node.component.forceUpdate();
node._vdom.component.forceUpdate();
expect(renderer.Reconciler.receiveComponent).to.be.called;
});

it('notifies dev tools when components are removed', () => {
const node = render(h(StatefulComponent), container);
unmountComponent(node.component, true);
unmountComponent(node._vdom.component, true);
expect(renderer.Reconciler.unmountComponent).to.be.called;
});

// Test properties of DOM components exposed to devtools via
// ReactDOMComponent-like instances
it('exposes the tag name of DOM components', () => {
const node = render(h(StatefulComponent), container);
const domInstance = domInstanceMap.get(node.base);
const domInstance = domInstanceMap.get(node);
expect(domInstance._currentElement.type).to.equal('span');
});

it('exposes DOM component props', () => {
const node = render(h(FunctionalComponent), container);
const domInstance = domInstanceMap.get(node.base);
const domInstance = domInstanceMap.get(node);
expect(domInstance._currentElement.props.class).to.equal('functional');
});

it('exposes text component contents', () => {
const node = render(h(Label, {label: 'Text content'}), container);
const textInstance = domInstanceMap.get(node.base);
const textInstance = domInstanceMap.get(node);
expect(textInstance._stringText).to.equal('Text content');
});

// Test properties of composite components exposed to devtools via
// ReactCompositeComponent-like instances
it('exposes the name of composite component classes', () => {
const node = render(h(StatefulComponent), container);
expect(instanceMap.get(node.base).getName()).to.equal('StatefulComponent');
expect(instanceMap.get(node).getName()).to.equal('StatefulComponent');
});

it('exposes composite component props', () => {
const node = render(h(Label, {label: 'Text content'}), container);
const instance = instanceMap.get(node.base);
const instance = instanceMap.get(node);
expect(instance._currentElement.props.label).to.equal('Text content');
});

it('exposes composite component state', () => {
const node = render(h(StatefulComponent), container);

node.component.setState({count: 42});
node.component.forceUpdate();
node._vdom.component.setState({count: 42});
node._vdom.component.forceUpdate();

expect(instanceMap.get(node.base).state).to.deep.equal({count: 42});
expect(instanceMap.get(node).state).to.deep.equal({count: 42});
});

// Test setting state via devtools
it('updates component when setting state from devtools', () => {
const node = render(h(StatefulComponent), container);

instanceMap.get(node.base).setState({count: 10});
instanceMap.get(node.base).forceUpdate();
instanceMap.get(node).setState({count: 10});
instanceMap.get(node).forceUpdate();

expect(node.base.textContent).to.equal('10');
expect(node.textContent).to.equal('10');
});

// Test that the original instance is exposed via `_instance` so it can
Expand All @@ -171,47 +171,47 @@ describe_('React Developer Tools integration', () => {

it('exposes the name of functional components', () => {
const node = render(h(FunctionalComponent), container);
const instance = instanceMap.get(node.base);
const instance = instanceMap.get(node);
expect(instance.getName()).to.equal('FunctionalComponent');
});

xit('exposes a fallback name if the component has no useful name', () => {
const node = render(h(() => h('div')), container);
const instance = instanceMap.get(node.base);
const instance = instanceMap.get(node);
expect(instance.getName()).to.equal('(Function.name missing)');
});

// Test handling of DOM children
it('notifies dev tools about DOM children', () => {
const node = render(h(StatefulComponent), container);
const domInstance = domInstanceMap.get(node.base);
const domInstance = domInstanceMap.get(node);
expect(renderer.Reconciler.mountComponent).to.have.been.calledWith(domInstance);
});

it('notifies dev tools when a component update adds DOM children', () => {
const node = render(h(MultiChild, {initialCount: 2}), container);

node.component.setState({count: 4});
node.component.forceUpdate();
node._vdom.component.setState({count: 4});
node._vdom.component.forceUpdate();

expect(renderer.Reconciler.mountComponent).to.have.been.called.twice;
});

it('notifies dev tools when a component update modifies DOM children', () => {
const node = render(h(StatefulComponent), container);

instanceMap.get(node.base).setState({count: 10});
instanceMap.get(node.base).forceUpdate();
instanceMap.get(node).setState({count: 10});
instanceMap.get(node).forceUpdate();

const textInstance = domInstanceMap.get(node.base.childNodes[0]);
const textInstance = domInstanceMap.get(node.childNodes[0]);
expect(textInstance._stringText).to.equal('10');
});

it('notifies dev tools when a component update removes DOM children', () => {
const node = render(h(MultiChild, {initialCount: 1}), container);

node.component.setState({count: 0});
node.component.forceUpdate();
node._vdom.component.setState({count: 0});
node._vdom.component.forceUpdate();

expect(renderer.Reconciler.unmountComponent).to.be.called;
});
Expand All @@ -229,7 +229,7 @@ describe_('React Developer Tools integration', () => {

it('removes root components when they are unmounted', () => {
const node = render(h(StatefulComponent), container);
unmountComponent(node.component, true);
unmountComponent(node._vdom.component, true);
expect(Object.keys(renderer.Mount._instancesByReactRootID).length).to.equal(0);
});

Expand Down
2 changes: 1 addition & 1 deletion test/browser/keys.js → test/browser/keys.jsd
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ describe('keys', () => {
root = render(<App opened loading />, scratch, root);
root = render(<App opened />, scratch, root);

let html = String(root.base.innerHTML).replace(/ class=""/g, '');
let html = String(root.innerHTML).replace(/ class=""/g, '');
expect(html).to.equal('<div>This div needs to be here for this to break</div><div></div><div class="indicator"><div>indicator</div><div>indicator</div><div>indicator</div></div>');
});
});
File renamed without changes.
File renamed without changes.
20 changes: 10 additions & 10 deletions test/browser/refs.js → test/browser/refs.jsd
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ describe('refs', () => {

it('should invoke refs in render()', () => {
let ref = spy('ref');
const vdom = render(<div ref={ref} />, scratch);
expect(ref).to.have.been.calledOnce.and.calledWith(vdom);
const dom = render(<div ref={ref} />, scratch);
expect(ref).to.have.been.calledOnce.and.calledWith(dom._vdom);
});

it('should invoke refs in Component.render()', () => {
let outer = spy('outer'),
inner = spy('inner');
let outer = spy('outer');
let inner = spy('inner');
class Foo extends Component {
render() {
return (
Expand All @@ -45,8 +45,8 @@ describe('refs', () => {
}
const vdom = render(<Foo />, scratch);

expect(outer).to.have.been.calledWith(vdom);
expect(inner).to.have.been.calledWith(vdom.children[0]);
expect(outer).to.have.been.calledWith(vdom._vdom);
expect(inner).to.have.been.calledWith(vdom.firstChild._vdom);
});

it('should pass components to ref functions', () => {
Expand Down Expand Up @@ -284,21 +284,21 @@ describe('refs', () => {
sinon.spy(Child.prototype, 'handleMount');

const vdom = render(<App />, scratch);
expect(inst.handleMount).to.have.been.calledOnce.and.calledWith(vdom.children[0]);
expect(inst.handleMount).to.have.been.calledOnce.and.calledWith(vdom.firstChild._vdom);
inst.handleMount.reset();

inst.setState({ show:true });
inst.forceUpdate();
expect(inst.handleMount).to.have.been.calledTwice;
expect(inst.handleMount.firstCall).to.have.been.calledWith(null);
expect(inst.handleMount.secondCall).to.have.been.calledWith(vdom.children[0]);
expect(inst.handleMount.secondCall).to.have.been.calledWith(vdom.firstChild._vdom);
inst.handleMount.reset();

inst.setState({ show:false });
inst.forceUpdate();
expect(inst.handleMount).to.have.been.calledTwice;
expect(inst.handleMount.firstCall).to.have.been.calledWith(null);
expect(inst.handleMount.secondCall).to.have.been.calledWith(vdom.children[0]);
expect(inst.handleMount.secondCall).to.have.been.calledWith(vdom.firstChild._vdom);
});


Expand All @@ -318,6 +318,6 @@ describe('refs', () => {
}

const vdom = render(<div><Wrapper ref={ c => ref(c.vdom) } /></div>, scratch, buildVDom(scratch.firstChild));
expect(ref).to.have.been.calledOnce.and.calledWith(vdom.children[0]);
expect(ref).to.have.been.calledOnce.and.calledWith(vdom.firstChild._vdom);
});
});
26 changes: 12 additions & 14 deletions test/browser/render.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* global DISABLE_FLAKEY */

import { h, render, Component, buildVDom } from '../../build/zreact';
import { h, render, Component } from '../../build/zreact';
/** @jsx h */

function getAttributes(node) {
Expand Down Expand Up @@ -153,19 +153,18 @@ describe('render()', () => {
});

it('should clear falsey input values', () => {
let vdom = render((
let root = render((
<div>
<input value={0} />
<input value={false} />
<input value={null} />
<input value={undefined} />
</div>
), scratch);
const root = vdom.base
expect(root.children[0]).to.have.property('value', '0');
expect(root.children[1]).to.have.property('value', 'false');
expect(root.children[2]).to.have.property('value', '');
expect(root.children[3]).to.have.property('value', '');
expect(root.childNodes[0]).to.have.property('value', '0');
expect(root.childNodes[1]).to.have.property('value', 'false');
expect(root.childNodes[2]).to.have.property('value', '');
expect(root.childNodes[3]).to.have.property('value', '');
});

it('should clear falsey DOM properties', () => {
Expand Down Expand Up @@ -323,12 +322,11 @@ describe('render()', () => {
let click = sinon.spy(),
focus = sinon.spy();

let vdom = render((
let root = render((
<div onClickCapture={click} onFocusCapture={focus}>
<button />
</div>
), scratch);
const root = vdom.base
root.firstElementChild.click();
root.firstElementChild.focus();

Expand Down Expand Up @@ -372,19 +370,19 @@ describe('render()', () => {
<div style={{ color: 'rgb(0, 255, 255)' }}>test</div>
), scratch, vdom);

expect(vdom.base.style).to.have.property('cssText').that.equals('color: rgb(0, 255, 255);');
expect(vdom.style).to.have.property('cssText').that.equals('color: rgb(0, 255, 255);');

vdom = render((
<div style="display: inline;">test</div>
), scratch, vdom);

expect(vdom.base.style).to.have.property('cssText').that.equals('display: inline;');
expect(vdom.style).to.have.property('cssText').that.equals('display: inline;');

vdom = render((
<div style={{ backgroundColor: 'rgb(0, 255, 255)' }}>test</div>
), scratch, vdom);

expect(vdom.base.style).to.have.property('cssText').that.equals('background-color: rgb(0, 255, 255);');
expect(vdom.style).to.have.property('cssText').that.equals('background-color: rgb(0, 255, 255);');
});

it('should support dangerouslySetInnerHTML', () => {
Expand Down Expand Up @@ -434,14 +432,14 @@ describe('render()', () => {
it('should hydrate with dangerouslySetInnerHTML', () => {
let html = '<b>foo &amp; bar</b>';
scratch.innerHTML = `<div>${html}</div>`;
render(<div dangerouslySetInnerHTML={{ __html: html }} />, scratch, buildVDom(scratch.lastChild));
render(<div dangerouslySetInnerHTML={{ __html: html }} />, scratch, scratch.lastChild);

expect(scratch.firstChild).to.have.property('innerHTML', html);
expect(scratch.innerHTML).to.equal(`<div>${html}</div>`);
});

it('should reconcile mutated DOM attributes', () => {
let check = p => render(<input type="checkbox" checked={p} />, scratch, buildVDom(scratch.lastChild)),
let check = p => render(<input type="checkbox" checked={p} />, scratch, scratch.lastChild),
value = () => scratch.lastChild.checked,
setValue = p => scratch.lastChild.checked = p;
check(true);
Expand Down
File renamed without changes.
File renamed without changes.

0 comments on commit 342efaa

Please sign in to comment.