parent
ef5ee212e3
commit
08300f67fe
|
@ -11,9 +11,10 @@
|
||||||
"inula-reactive": "workspace:^0.0.1"
|
"inula-reactive": "workspace:^0.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"jsdom": "^24.0.0",
|
|
||||||
"@testing-library/user-event": "^12.1.10",
|
"@testing-library/user-event": "^12.1.10",
|
||||||
"@vitest/ui": "^0.34.5",
|
"@vitest/ui": "^0.34.5",
|
||||||
|
"jsdom": "^24.0.0",
|
||||||
|
"vite-plugin-inula-no-vdom": "workspace:*",
|
||||||
"vitest": "^1.2.2"
|
"vitest": "^1.2.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -389,3 +389,7 @@ export function bindRef<T>(node: T, ref: RefObject<T> | RefCallback<T>): void {
|
||||||
export function createElement(tag: string) {
|
export function createElement(tag: string) {
|
||||||
return document.createElement(tag);
|
return document.createElement(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createText(text: string) {
|
||||||
|
return document.createTextNode(text);
|
||||||
|
}
|
||||||
|
|
|
@ -31,6 +31,17 @@ export function delegateEvents(eventNames: string[], node: Node = window.documen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function delegateEvent(source: HTMLElement, eventName: string, listener: EventListener, delegator: Node = window.document): void {
|
||||||
|
const events: Set<string> = delegator[DELEGATE_EVENTS_KEY] || (delegator[DELEGATE_EVENTS_KEY] = new Set());
|
||||||
|
|
||||||
|
if (!events.has(eventName)) {
|
||||||
|
events.add(eventName);
|
||||||
|
delegator.addEventListener(eventName, eventHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
source[`$$DELEGATE_EVENT_${eventName}`] = listener;
|
||||||
|
}
|
||||||
|
|
||||||
export function clearDelegatedEvents(node: Node = window.document): void {
|
export function clearDelegatedEvents(node: Node = window.document): void {
|
||||||
const events: Set<string> | undefined = node[DELEGATE_EVENTS_KEY];
|
const events: Set<string> | undefined = node[DELEGATE_EVENTS_KEY];
|
||||||
if (events) {
|
if (events) {
|
||||||
|
|
|
@ -22,25 +22,17 @@ import {
|
||||||
style as $$style,
|
style as $$style,
|
||||||
className as $$className,
|
className as $$className,
|
||||||
setAttribute as $$attr,
|
setAttribute as $$attr,
|
||||||
createElement
|
createElement,
|
||||||
|
createText,
|
||||||
|
insert,
|
||||||
} from '../src/dom';
|
} from '../src/dom';
|
||||||
import { runComponent as $$runComponent, render } from '../src/core';
|
import { runComponent as $$runComponent, render, runComponent as createComponent } from '../src/core';
|
||||||
import { delegateEvents as $$delegateEvents, addEventListener as $$on } from '../src/event';
|
import { delegateEvents as $$delegateEvents, addEventListener as $$on, delegateEvent } from '../src/event';
|
||||||
import { describe, expect } from 'vitest';
|
import { describe, expect } from 'vitest';
|
||||||
import { domTest as it } from './utils';
|
import { domTest as it } from './utils';
|
||||||
|
|
||||||
describe('render', () => {
|
describe('render', () => {
|
||||||
it('should render plain jsx', ({ container }) => {
|
it('should render plain jsx', ({ container }) => {
|
||||||
/**
|
|
||||||
* 源码:
|
|
||||||
* const CountingComponent = () => {
|
|
||||||
* return <div id="count">Count value is 0.</div>;
|
|
||||||
* };
|
|
||||||
*
|
|
||||||
* render(() => <CountingComponent />, container);
|
|
||||||
*/
|
|
||||||
|
|
||||||
// 编译后:
|
|
||||||
const CountingComponent = () => {
|
const CountingComponent = () => {
|
||||||
return <div id="count">Count value is 0.</div>;
|
return <div id="count">Count value is 0.</div>;
|
||||||
};
|
};
|
||||||
|
@ -50,139 +42,59 @@ describe('render', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render jsx expression with slots', ({ container }) => {
|
it('should render jsx expression with slots', ({ container }) => {
|
||||||
/**
|
|
||||||
* 源码:
|
|
||||||
* const CountingComponent = () => {
|
|
||||||
* return <div id="count">Count value is {0}.</div>;
|
|
||||||
* };
|
|
||||||
*
|
|
||||||
* render(() => <CountingComponent />, container);
|
|
||||||
*/
|
|
||||||
|
|
||||||
// 编译后:
|
|
||||||
const $tmpl = /*#__PURE__*/ $$template('<div id="count">Count value is <!>.');
|
|
||||||
const CountingComponent = () => {
|
const CountingComponent = () => {
|
||||||
return (() => {
|
return <div id="count">Count value is {0}.</div>;
|
||||||
const _el$ = $tmpl(),
|
|
||||||
_el$2 = _el$.firstChild,
|
|
||||||
_el$4 = _el$2.nextSibling;
|
|
||||||
$$insert(_el$, 0, _el$4);
|
|
||||||
return _el$;
|
|
||||||
})();
|
|
||||||
};
|
};
|
||||||
render(() => $$runComponent(CountingComponent, {}), container);
|
render(() => $$runComponent(CountingComponent, {}), container);
|
||||||
|
|
||||||
expect(container.querySelector('#count').innerHTML).toEqual('Count value is 0<!---->.');
|
expect(container.querySelector('#count').innerHTML).toEqual('Count value is 0.');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render fragment', ({ container }) => {
|
it('should render fragment', ({ container }) => {
|
||||||
/**
|
|
||||||
* 源码:
|
|
||||||
* const CountingComponent = () => {
|
|
||||||
* const [count, setCount] = createSignal(0);
|
|
||||||
* const add = () => {
|
|
||||||
* setCount((c) => c + 1);
|
|
||||||
* }
|
|
||||||
* return <>
|
|
||||||
* <div id="count">Count value is {count()}.</div>
|
|
||||||
* <div><button onClick={add}>add</button></div>
|
|
||||||
* </>;
|
|
||||||
* };
|
|
||||||
*/
|
|
||||||
|
|
||||||
// 编译后:
|
|
||||||
const $tmpl = /*#__PURE__*/ $$template('<div id="count">Count value is <!>.'),
|
|
||||||
$tmpl_2 = /*#__PURE__*/ $$template('<div><button id="btn">add');
|
|
||||||
const CountingComponent = () => {
|
const CountingComponent = () => {
|
||||||
const count = reactive(0);
|
const count = reactive(0);
|
||||||
const add = () => {
|
const add = () => {
|
||||||
count.set(c => c + 1);
|
count.set(c => c + 1);
|
||||||
};
|
};
|
||||||
return [
|
return (
|
||||||
(() => {
|
<>
|
||||||
const _el$ = $tmpl(),
|
<div id="count">Count value is {count.get()}.</div>
|
||||||
_el$2 = _el$.firstChild,
|
<div>
|
||||||
_el$4 = _el$2.nextSibling;
|
<button id="btn" onClick={add}>add</button>
|
||||||
$$insert(_el$, count, _el$4);
|
</div>
|
||||||
return _el$;
|
</>
|
||||||
})(),
|
);
|
||||||
(() => {
|
|
||||||
const _el$5 = $tmpl_2(),
|
|
||||||
_el$6 = _el$5.firstChild;
|
|
||||||
$$on(_el$6, 'click', add, true);
|
|
||||||
return _el$5;
|
|
||||||
})(),
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
render(() => $$runComponent(CountingComponent, {}), container);
|
render(() => $$runComponent(CountingComponent, {}), container);
|
||||||
|
|
||||||
$$delegateEvents(['click']);
|
|
||||||
|
|
||||||
container.querySelector('#btn').click();
|
container.querySelector('#btn').click();
|
||||||
|
|
||||||
expect(container.querySelector('#count').innerHTML).toEqual('Count value is 1<!---->.');
|
expect(container.querySelector('#count').innerHTML).toEqual('Count value is 1.');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render components', ({ container }) => {
|
it('should render components', ({ container }) => {
|
||||||
/**
|
|
||||||
* 源码:
|
|
||||||
* const CountValue = (props) => {
|
|
||||||
* return <div id="count">Count value is {props.count} .</div>;
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* const CountingComponent = () => {
|
|
||||||
* const [count, setCount] = createSignal(0);
|
|
||||||
* const add = () => {
|
|
||||||
* setCount((c) => c + 1);
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* return <div>
|
|
||||||
* <CountValue count={count} />
|
|
||||||
* <div><button onClick={add}>add</button></div>
|
|
||||||
* </div>;
|
|
||||||
* };
|
|
||||||
*
|
|
||||||
* render(() => <CountingComponent />, document.getElementById("app"));
|
|
||||||
*/
|
|
||||||
|
|
||||||
// 编译后:
|
|
||||||
const $tmpl = /*#__PURE__*/ $$template('<div id="count">Count value is <!>.'),
|
|
||||||
$tmpl_2 = /*#__PURE__*/ $$template('<div><div><button id="btn">add');
|
|
||||||
const CountValue = props => {
|
const CountValue = props => {
|
||||||
return (() => {
|
return <div id="count">Count value is {props.count} .</div>;
|
||||||
const _el$ = $tmpl(),
|
|
||||||
_el$2 = _el$.firstChild,
|
|
||||||
_el$4 = _el$2.nextSibling;
|
|
||||||
$$insert(_el$, () => props.count, _el$4);
|
|
||||||
return _el$;
|
|
||||||
})();
|
|
||||||
};
|
};
|
||||||
const CountingComponent = () => {
|
const CountingComponent = () => {
|
||||||
const count = reactive(0);
|
const count = reactive(0);
|
||||||
const add = () => {
|
const add = () => {
|
||||||
count.set(c => c + 1);
|
count.set(c => c + 1);
|
||||||
};
|
};
|
||||||
return (() => {
|
return (
|
||||||
const _el$5 = $tmpl_2(),
|
<div>
|
||||||
_el$6 = _el$5.firstChild,
|
<CountValue count={count} />
|
||||||
_el$7 = _el$6.firstChild;
|
<div>
|
||||||
$$insert(
|
<button id="btn" onClick={add}>add</button>
|
||||||
_el$5,
|
</div>
|
||||||
$$runComponent(CountValue, {
|
</div>
|
||||||
count: count,
|
);
|
||||||
}),
|
|
||||||
_el$6
|
|
||||||
);
|
|
||||||
$$on(_el$7, 'click', add, true);
|
|
||||||
return _el$5;
|
|
||||||
})();
|
|
||||||
};
|
};
|
||||||
render(() => $$runComponent(CountingComponent, {}), container);
|
render(() => $$runComponent(CountingComponent, {}), container);
|
||||||
$$delegateEvents(['click']);
|
|
||||||
|
|
||||||
container.querySelector('#btn').click();
|
container.querySelector('#btn').click();
|
||||||
|
|
||||||
expect(container.querySelector('#count').innerHTML).toEqual('Count value is 1<!---->.');
|
expect(container.querySelector('#count').innerHTML).toEqual('Count value is 1.');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render components with slot', ({ container }) => {
|
it('should render components with slot', ({ container }) => {
|
||||||
|
|
|
@ -28,7 +28,7 @@ export class HTMLPropGenerator extends BaseGenerator {
|
||||||
])
|
])
|
||||||
|
|
||||||
addHTMLProp(
|
addHTMLProp(
|
||||||
nodeName: string,
|
nodeName: string,
|
||||||
tag: string,
|
tag: string,
|
||||||
key: string,
|
key: string,
|
||||||
value: t.Expression,
|
value: t.Expression,
|
||||||
|
@ -45,7 +45,7 @@ export class HTMLPropGenerator extends BaseGenerator {
|
||||||
* setStyle($node, value)
|
* setStyle($node, value)
|
||||||
*/
|
*/
|
||||||
private setStyle(
|
private setStyle(
|
||||||
nodeName: string,
|
nodeName: string,
|
||||||
value: t.Expression,
|
value: t.Expression,
|
||||||
) {
|
) {
|
||||||
return this.t.callExpression(
|
return this.t.callExpression(
|
||||||
|
@ -59,7 +59,7 @@ export class HTMLPropGenerator extends BaseGenerator {
|
||||||
* setDataset($node, value)
|
* setDataset($node, value)
|
||||||
*/
|
*/
|
||||||
private setDataset(
|
private setDataset(
|
||||||
nodeName: string,
|
nodeName: string,
|
||||||
value: t.Expression,
|
value: t.Expression,
|
||||||
) {
|
) {
|
||||||
return this.t.callExpression(
|
return this.t.callExpression(
|
||||||
|
@ -73,7 +73,7 @@ export class HTMLPropGenerator extends BaseGenerator {
|
||||||
* $node.key = value
|
* $node.key = value
|
||||||
*/
|
*/
|
||||||
private setStaticProperty(
|
private setStaticProperty(
|
||||||
nodeName: string,
|
nodeName: string,
|
||||||
key: string,
|
key: string,
|
||||||
value: t.Expression,
|
value: t.Expression,
|
||||||
) {
|
) {
|
||||||
|
@ -92,7 +92,7 @@ export class HTMLPropGenerator extends BaseGenerator {
|
||||||
* setProperty($node, key, value)
|
* setProperty($node, key, value)
|
||||||
*/
|
*/
|
||||||
private setDynamicProperty(
|
private setDynamicProperty(
|
||||||
nodeName: string,
|
nodeName: string,
|
||||||
key: string,
|
key: string,
|
||||||
value: t.Expression,
|
value: t.Expression,
|
||||||
) {
|
) {
|
||||||
|
@ -107,7 +107,7 @@ export class HTMLPropGenerator extends BaseGenerator {
|
||||||
* $node.setAttribute(key, value)
|
* $node.setAttribute(key, value)
|
||||||
*/
|
*/
|
||||||
private setStaticAttribute(
|
private setStaticAttribute(
|
||||||
nodeName: string,
|
nodeName: string,
|
||||||
key: string,
|
key: string,
|
||||||
value: t.Expression,
|
value: t.Expression,
|
||||||
) {
|
) {
|
||||||
|
@ -126,7 +126,7 @@ export class HTMLPropGenerator extends BaseGenerator {
|
||||||
* setAttribute($node, key, value)
|
* setAttribute($node, key, value)
|
||||||
*/
|
*/
|
||||||
private setDynamicAttribute(
|
private setDynamicAttribute(
|
||||||
nodeName: string,
|
nodeName: string,
|
||||||
key: string,
|
key: string,
|
||||||
value: t.Expression,
|
value: t.Expression,
|
||||||
) {
|
) {
|
||||||
|
@ -141,12 +141,12 @@ export class HTMLPropGenerator extends BaseGenerator {
|
||||||
* delegateEvent($node, eventName, value)
|
* delegateEvent($node, eventName, value)
|
||||||
*/
|
*/
|
||||||
private setDelegatedEvent(
|
private setDelegatedEvent(
|
||||||
nodeName: string,
|
nodeName: string,
|
||||||
eventName: string,
|
eventName: string,
|
||||||
value: t.Expression,
|
value: t.Expression,
|
||||||
) {
|
) {
|
||||||
return this.t.callExpression(
|
return this.t.callExpression(
|
||||||
this.t.identifier(this.importMap.delegateEvent),
|
this.t.identifier(this.importMap.delegateEvents),
|
||||||
[this.t.identifier(nodeName), this.t.stringLiteral(eventName), value]
|
[this.t.identifier(nodeName), this.t.stringLiteral(eventName), value]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ export class HTMLPropGenerator extends BaseGenerator {
|
||||||
* $node.addEventListener(eventName, value)
|
* $node.addEventListener(eventName, value)
|
||||||
*/
|
*/
|
||||||
private setStaticEvent(
|
private setStaticEvent(
|
||||||
nodeName: string,
|
nodeName: string,
|
||||||
eventName: string,
|
eventName: string,
|
||||||
value: t.Expression,
|
value: t.Expression,
|
||||||
) {
|
) {
|
||||||
|
@ -174,7 +174,7 @@ export class HTMLPropGenerator extends BaseGenerator {
|
||||||
* addEventListener($node, eventName, value)
|
* addEventListener($node, eventName, value)
|
||||||
*/
|
*/
|
||||||
private setDynamicEvent(
|
private setDynamicEvent(
|
||||||
nodeName: string,
|
nodeName: string,
|
||||||
eventName: string,
|
eventName: string,
|
||||||
value: t.Expression,
|
value: t.Expression,
|
||||||
) {
|
) {
|
||||||
|
@ -185,7 +185,7 @@ export class HTMLPropGenerator extends BaseGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private setDynamicHTMLProp(
|
private setDynamicHTMLProp(
|
||||||
nodeName: string,
|
nodeName: string,
|
||||||
tag: string,
|
tag: string,
|
||||||
key: string,
|
key: string,
|
||||||
value: t.Expression,
|
value: t.Expression,
|
||||||
|
@ -220,4 +220,4 @@ export class HTMLPropGenerator extends BaseGenerator {
|
||||||
this.elementAttributeMap[tag]?.includes(attribute)
|
this.elementAttributeMap[tag]?.includes(attribute)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue