!138 fix(no-vdom): modify event

* fix(no-vdom): modify event
* Merge branch 'reactive' of https://gitee.com/openInula/inula into reactive
* fix(no-vdom): modify test code's name rule
* Merge branch 'reactive' of https://gitee.com/openInula/inula into reactive
* fix(no-vdom): delete no-vnode module
* fix(no-vdom): update render function
* Merge branch 'reactive' of https://gitee.com/openInula/inula into reactive
* Merge branch 'reactive' of https://gitee.com/openInula/inula into reactive
* Merge remote-tracking branch 'origin/reactive' into reactive
* fix(no-vdom): add TS
* fix(no-vdom): change js 2 ts
This commit is contained in:
陈超涛 2024-02-07 07:30:29 +00:00
parent c7d039cfe3
commit cf87ab2183
8 changed files with 110 additions and 107 deletions

View File

@ -13,12 +13,12 @@
* See the Mulan PSL v2 for more details.
*/
import {insert} from './dom';
import { insert } from './dom';
type ComponentConstructor<T> = (props: T) => any;
type CodeFunction = () => any;
export function createComponent<T>(Comp: ComponentConstructor<T>, props: T = {} as T): any {
export function runComponent<T>(Comp: ComponentConstructor<T>, props: T = {} as T): any {
return Comp(props);
}

View File

@ -290,7 +290,7 @@ export function setAttribute(node: Element, name: string, value: string | null):
}
}
export function className(node: Element, value: string | Record<string, boolean> | null): void {
export function className(node: Element, value: string | string[] | Record<string, boolean> | null): void {
if (value == null) {
node.removeAttribute('class');
} else {

View File

@ -13,41 +13,45 @@
* See the Mulan PSL v2 for more details.
*/
const $$EVENTS = '_$DX_DELEGATE';
const DELEGATE_EVENTS_KEY = '$$DELEGATE_EVENTS';
/**
* document上注册事件
* @param eventNames
* @param document window.documentdocument对象
* Delegate events on the DOM
* @param eventNames eventNames Array of event names
* @param node node Default is window.document, other document objects can be passed in
*/
export function delegateEvents(eventNames: string[], document: Document = window.document): void {
const e: Set<string> = document[$$EVENTS] || (document[$$EVENTS] = new Set());
for (let i = 0, l = eventNames.length; i < l; i++) {
const name = eventNames[i];
if (!e.has(name)) {
e.add(name);
document.addEventListener(name, eventHandler);
export function delegateEvents(eventNames: string[], node: Node = window.document): void {
const events: Set<string> = node[DELEGATE_EVENTS_KEY] || (node[DELEGATE_EVENTS_KEY] = new Set());
for (const name of eventNames) {
if (!events.has(name)) {
events.add(name);
node.addEventListener(name, eventHandler);
}
}
}
export function clearDelegatedEvents(document: Document = window.document): void {
const events: Set<string> | undefined = document[$$EVENTS];
export function clearDelegatedEvents(node: Node = window.document): void {
const events: Set<string> | undefined = node[DELEGATE_EVENTS_KEY];
if (events) {
for (const name of events.keys()) document.removeEventListener(name, eventHandler);
delete document[$$EVENTS];
for (const name of Array.from(events.keys())) {
node.removeEventListener(name, eventHandler);
}
delete node[DELEGATE_EVENTS_KEY];
}
}
function eventHandler(e: Event) {
const key = `$$${e.type}`;
let node: EventTarget & Element = (e.composedPath && e.composedPath()[0]) || e.target;
if (e.target !== node) {
Object.defineProperty(e, 'target', {
configurable: true,
value: node,
});
if (!e.target) {
throw new Error('Event triggered without a target');
}
const key = `$$DELEGATE_EVENT_${e.type}`;
// target refer to that triggers the event
let node: EventTarget = e.target;
// currentTarget will always refer to the object that registered the event listener
Object.defineProperty(e, 'currentTarget', {
configurable: true,
get() {
@ -55,23 +59,22 @@ function eventHandler(e: Event) {
},
});
// 冒泡执行事件
// bubble execution event handler
while (node) {
const handler = node[key] as EventListener | undefined;
if (handler && !node.disabled) {
const data = node[`${key}Data` as keyof typeof node];
data !== undefined ? handler.call(node, data, e) : handler.call(node, e);
if (handler) {
handler.call(node, e);
if (e.cancelBubble) {
return;
}
}
node = (node as any)._$host || node.parentNode || (node as any).host;
node = (node as Node).parentNode as Element;
}
}
export function addEventListener(node: Element, name: string, handler: EventListener, delegate?: boolean): void {
if (delegate) {
node[`$$${name}`] = handler;
node[`$$DELEGATE_EVENT_${name}`] = handler;
} else {
node.addEventListener(name, handler);
}

View File

@ -19,8 +19,8 @@ import {
insert as $$insert,
setAttribute as $$setAttribute,
} from '../src/dom';
import { createComponent as $$createComponent, render } from '../src/core';
import { delegateEvents as $$delegateEvents, addEventListener as $$addEventListener } from '../src/event';
import { runComponent as $$runComponent, render } from '../src/core';
import { delegateEvents as $$delegateEvents, addEventListener as $$on } from '../src/event';
import { For } from '../src/components/For';
const container = document.createElement('div');
@ -84,7 +84,7 @@ bench('For', () => {
* <div>
* <div>
* <div>
* <div><h1>Horizon-reactive-novnode</h1></div>
* <div><h1>Inula For</h1></div>
* <div>
* <div>
* <Button id="run" title="Create 1,000 rows" cb={run}/>
@ -106,7 +106,7 @@ bench('For', () => {
const $tmpl = /*#__PURE__*/ $$template('<tr><td class="col-md-1">'),
$tmpl_2 = /*#__PURE__*/ $$template('<div class="col-sm-6"><button type="button">'),
$tmpl_3 = /*#__PURE__*/ $$template(
'<div><div><div><div><h1>Horizon-reactive-novnode</h1></div><div><div></div></div></div></div><table><tbody id="tbody">'
'<div><div><div><div><h1>Inula For</h1></div><div><div></div></div></div></div><table><tbody id="tbody">'
);
const A = [
'pretty',
@ -162,12 +162,12 @@ bench('For', () => {
})();
};
const RowList = props => {
return $$createComponent(For, {
return $$runComponent(For, {
get each() {
return props.list;
},
children: item =>
$$createComponent(Row, {
$$runComponent(Row, {
item: item,
}),
});
@ -176,7 +176,7 @@ bench('For', () => {
(() => {
const _el$3 = $tmpl_2(),
_el$4 = _el$3.firstChild;
$$addEventListener(_el$4, 'click', props.cb, true);
$$on(_el$4, 'click', props.cb, true);
$$insert(_el$4, () => props.title);
watch(() => $$setAttribute(_el$4, 'id', props.id));
return _el$3;
@ -211,7 +211,7 @@ bench('For', () => {
_el$12 = _el$11.firstChild;
$$insert(
_el$10,
$$createComponent(Button, {
$$runComponent(Button, {
id: 'run',
title: 'Create 1,000 rows',
cb: run,
@ -219,7 +219,7 @@ bench('For', () => {
);
$$insert(
_el$12,
$$createComponent(RowList, {
$$runComponent(RowList, {
get list() {
return state.list;
},
@ -228,7 +228,7 @@ bench('For', () => {
return _el$5;
})();
};
render(() => $$createComponent(Main, {}), container);
render(() => $$runComponent(Main, {}), container);
$$delegateEvents(['click']);
container.querySelector('#run').click();

View File

@ -21,8 +21,8 @@ import {
insert as $$insert,
setAttribute as $$setAttribute,
} from '../src/dom';
import { createComponent as $$createComponent, render } from '../src/core';
import { delegateEvents as $$delegateEvents, addEventListener as $$addEventListener } from '../src/event';
import { runComponent as $$runComponent, render } from '../src/core';
import { delegateEvents as $$delegateEvents, addEventListener as $$on } from '../src/event';
import { describe, expect } from 'vitest';
import { domTest as it } from './utils';
import { For } from '../src/components/For';
@ -138,26 +138,26 @@ describe('For', () => {
_el$10 = _el$9.firstChild;
$$insert(
_el$6,
$$createComponent(For, {
$$runComponent(For, {
get each() {
return state.todoList;
},
children: todo => [
$$createComponent(Todo, {
$$runComponent(Todo, {
todo: todo,
}),
$$createComponent(Todo, {
$$runComponent(Todo, {
todo: todo,
}),
],
})
);
_el$8.$$click = add;
_el$10.$$click = push;
$$on(_el$8, 'click', add);
$$on(_el$10, 'click', push);
return _el$5;
})();
};
render(() => $$createComponent(CountingComponent, {}), container);
render(() => $$runComponent(CountingComponent, {}), container);
$$delegateEvents(['click']);
expect(container.querySelector('#todos').innerHTML).toEqual(
@ -313,12 +313,12 @@ describe('For', () => {
})();
};
const RowList = props => {
return $$createComponent(For, {
return $$runComponent(For, {
get each() {
return props.list;
},
children: item =>
$$createComponent(Row, {
$$runComponent(Row, {
item: item,
}),
});
@ -327,7 +327,7 @@ describe('For', () => {
(() => {
const _el$3 = $tmpl_2(),
_el$4 = _el$3.firstChild;
$$addEventListener(_el$4, 'click', props.cb, true);
$$on(_el$4, 'click', props.cb, true);
$$insert(_el$4, () => props.title);
watch(() => $$setAttribute(_el$4, 'id', props.id));
return _el$3;
@ -362,7 +362,7 @@ describe('For', () => {
_el$12 = _el$11.firstChild;
$$insert(
_el$10,
$$createComponent(Button, {
$$runComponent(Button, {
id: 'run',
title: 'Create 1,000 rows',
cb: run,
@ -370,7 +370,7 @@ describe('For', () => {
);
$$insert(
_el$12,
$$createComponent(RowList, {
$$runComponent(RowList, {
get list() {
return state.list;
},
@ -379,7 +379,7 @@ describe('For', () => {
return _el$5;
})();
};
render(() => $$createComponent(Main, {}), container);
render(() => $$runComponent(Main, {}), container);
$$delegateEvents(['click']);
expect(container.querySelector('#tbody').innerHTML).toEqual(

View File

@ -18,8 +18,8 @@
import { describe, expect, vi } from 'vitest';
import { domTest as it } from './utils';
import { template as $$template } from '../src/dom';
import { createComponent as $$createComponent, render } from '../src/core';
import { delegateEvents as $$delegateEvents, addEventListener as $$addEventListener } from '../src/event';
import { runComponent as $$runComponent, render } from '../src/core';
import { delegateEvents as $$delegateEvents, addEventListener as $$on } from '../src/event';
function dispatchMouseEvent(element: HTMLElement, eventType = 'click') {
element.dispatchEvent(new MouseEvent(eventType, { bubbles: true }));
@ -67,37 +67,37 @@ describe('event', () => {
return [
(() => {
const _el$ = $tmpl();
$$addEventListener(_el$, 'change', () => fn('bound'));
$$on(_el$, 'change', () => fn('bound'));
return _el$;
})(),
(() => {
const _el$2 = $tmpl_2();
$$addEventListener(_el$2, 'change', handler);
$$on(_el$2, 'change', handler);
return _el$2;
})(),
(() => {
const _el$3 = $tmpl_3();
$$addEventListener(_el$3, 'change', fn);
$$on(_el$3, 'change', fn);
return _el$3;
})(),
(() => {
const _el$4 = $tmpl_4();
$$addEventListener(_el$4, 'click', () => fn('delegated'));
$$on(_el$4, 'click', () => fn('delegated'));
return _el$4;
})(),
(() => {
const _el$5 = $tmpl_5();
$$addEventListener(_el$5, 'click', handler);
$$on(_el$5, 'click', handler);
return _el$5;
})(),
(() => {
const _el$6 = $tmpl_6();
$$addEventListener(_el$6, 'click', fn);
$$on(_el$6, 'click', fn);
return _el$6;
})(),
];
};
render(() => $$createComponent(Comp), container);
render(() => $$runComponent(Comp), container);
$$delegateEvents(['click']);
dispatchChangeEvent(document.getElementById('inline-fn-change'), 'change');

View File

@ -23,8 +23,8 @@ import {
style as $$style,
className as $$className,
} from '../src/dom';
import { createComponent as $$createComponent, render } from '../src/core';
import { delegateEvents as $$delegateEvents, addEventListener as $$addEventListener } from '../src/event';
import { runComponent as $$runComponent, render } from '../src/core';
import { delegateEvents as $$delegateEvents, addEventListener as $$on } from '../src/event';
import { describe, expect } from 'vitest';
import { domTest as it } from './utils';
import { Show } from '../src/components/Show';
@ -46,7 +46,7 @@ describe('render', () => {
const CountingComponent = () => {
return $tmpl();
};
render(() => $$createComponent(CountingComponent, {}), container);
render(() => $$runComponent(CountingComponent, {}), container);
expect(container.querySelector('#count').innerHTML).toEqual('Count value is 0.');
});
@ -72,7 +72,7 @@ describe('render', () => {
return _el$;
})();
};
render(() => $$createComponent(CountingComponent, {}), container);
render(() => $$runComponent(CountingComponent, {}), container);
expect(container.querySelector('#count').innerHTML).toEqual('Count value is 0<!---->.');
});
@ -111,12 +111,12 @@ describe('render', () => {
(() => {
const _el$5 = $tmpl_2(),
_el$6 = _el$5.firstChild;
_el$6.$$click = add;
$$on(_el$6, 'click', add, true);
return _el$5;
})(),
];
};
render(() => $$createComponent(CountingComponent, {}), container);
render(() => $$runComponent(CountingComponent, {}), container);
$$delegateEvents(['click']);
@ -170,16 +170,16 @@ describe('render', () => {
_el$7 = _el$6.firstChild;
$$insert(
_el$5,
$$createComponent(CountValue, {
$$runComponent(CountValue, {
count: count,
}),
_el$6
);
_el$7.$$click = add;
$$on(_el$7, 'click', add, true);
return _el$5;
})();
};
render(() => $$createComponent(CountingComponent, {}), container);
render(() => $$runComponent(CountingComponent, {}), container);
$$delegateEvents(['click']);
container.querySelector('#btn').click();
@ -247,17 +247,17 @@ describe('render', () => {
_el$8 = _el$7.firstChild;
$$insert(
_el$6,
$$createComponent(CountValue, {
$$runComponent(CountValue, {
count: count,
}),
_el$7
);
_el$8.$$click = add;
$$insert(_el$6, $$createComponent(Nested, {}), null);
$$on(_el$8, 'click', add, true);
$$insert(_el$6, $$runComponent(Nested, {}), null);
return _el$6;
})();
};
render(() => $$createComponent(CountingComponent, {}), container);
render(() => $$runComponent(CountingComponent, {}), container);
$$delegateEvents(['click']);
expect(container.querySelector('h1').innerHTML).toMatchInlineSnapshot('"0"');
@ -280,7 +280,7 @@ describe('render', () => {
const Comp = () => {
return $tmpl();
};
render(() => $$createComponent(Comp, {}), container);
render(() => $$runComponent(Comp, {}), container);
expect(container.querySelector('div').style.color).toEqual('red');
});
@ -302,7 +302,7 @@ describe('render', () => {
return $tmpl();
};
render(() => $$createComponent(Comp, {}), container);
render(() => $$runComponent(Comp, {}), container);
expect(container.querySelector('div').style.color).toEqual('red');
});
@ -323,7 +323,7 @@ describe('render', () => {
return _el$;
})();
};
render(() => $$createComponent(Comp, {}), container);
render(() => $$runComponent(Comp, {}), container);
expect(container.querySelector('div').style.color).toEqual('red');
});
@ -346,7 +346,7 @@ describe('render', () => {
})();
};
render(() => $$createComponent(Comp, {}), container);
render(() => $$runComponent(Comp, {}), container);
expect(container.querySelector('div').style.color).toEqual('red');
});
@ -371,7 +371,7 @@ describe('render', () => {
})();
};
render(() => $$createComponent(Comp, {}), container);
render(() => $$runComponent(Comp, {}), container);
expect(container.querySelector('div').style.color).toEqual('red');
container.querySelector('div').style.color = 'green';
expect(container.querySelector('div').style.color).toEqual('green');
@ -396,7 +396,7 @@ describe('render', () => {
})();
};
render(() => $$createComponent(Comp, {}), container);
render(() => $$runComponent(Comp, {}), container);
expect(container.querySelector('div').style.color).toEqual('red');
container.querySelector('div').style.color = 'green';
expect(container.querySelector('div').style.color).toEqual('green');
@ -414,7 +414,7 @@ describe('render', () => {
const Comp = () => {
return $tmpl();
};
render(() => $$createComponent(Comp, {}), container);
render(() => $$runComponent(Comp, {}), container);
expect(container.querySelector('div').className).toEqual('red');
});
@ -436,7 +436,7 @@ describe('render', () => {
return _el$;
})();
};
render(() => $$createComponent(Comp, {}), container);
render(() => $$runComponent(Comp, {}), container);
expect(container.querySelector('div').className).toEqual('red');
});
@ -458,7 +458,7 @@ describe('render', () => {
return _el$;
})();
};
render(() => $$createComponent(Comp, {}), container);
render(() => $$runComponent(Comp, {}), container);
expect(container.querySelector('div').className).toEqual('red');
});
@ -478,7 +478,7 @@ describe('render', () => {
return _el$;
})();
};
render(() => $$createComponent(Comp, {}), container);
render(() => $$runComponent(Comp, {}), container);
expect(container.querySelector('div').className).toEqual('red green');
});
@ -500,7 +500,7 @@ describe('render', () => {
return _el$;
})();
};
render(() => $$createComponent(Comp, {}), container);
render(() => $$runComponent(Comp, {}), container);
expect(container.querySelector('div').className).toEqual('red');
container.querySelector('div').className = 'green';
expect(container.querySelector('div').className).toEqual('green');
@ -528,7 +528,7 @@ describe('render', () => {
return _el$;
})();
};
render(() => $$createComponent(Comp, {}), container);
render(() => $$runComponent(Comp, {}), container);
expect(container.querySelector('div').className).toEqual('red');
});
@ -550,7 +550,7 @@ describe('render', () => {
return _el$;
})();
};
render(() => $$createComponent(Comp, {}), container);
render(() => $$runComponent(Comp, {}), container);
expect(container.querySelector('div').className).toEqual('red green');
});
@ -601,28 +601,28 @@ describe('render', () => {
_el$7 = _el$6.firstChild;
$$insert(
_el$5,
$$createComponent(Show, {
$$runComponent(Show, {
get if() {
return computed(() => count.get() > 0);
},
get else() {
return $$createComponent(CountValue, {
return $$runComponent(CountValue, {
count: 999,
});
},
get children() {
return $$createComponent(CountValue, {
return $$runComponent(CountValue, {
count: count,
});
},
}),
_el$6
);
_el$7.$$click = add;
$$on(_el$7, 'click', add, true);
return _el$5;
})();
};
render(() => $$createComponent(CountingComponent, {}), container);
render(() => $$runComponent(CountingComponent, {}), container);
$$delegateEvents(['click']);
expect(container.querySelector('#count').innerHTML).toEqual('Count value is 999<!---->.');
@ -742,26 +742,26 @@ describe('render', () => {
_el$10 = _el$9.firstChild;
$$insert(
_el$6,
$$createComponent(For, {
$$runComponent(For, {
get each() {
return state.todoList;
},
children: todo => [
$$createComponent(Todo, {
$$runComponent(Todo, {
todo: todo,
}),
$$createComponent(Todo, {
$$runComponent(Todo, {
todo: todo,
}),
],
})
);
_el$8.$$click = add;
_el$10.$$click = push;
$$on(_el$8, 'click', add, true);
$$on(_el$10, 'click', push, true);
return _el$5;
})();
};
render(() => $$createComponent(CountingComponent, {}), container);
render(() => $$runComponent(CountingComponent, {}), container);
$$delegateEvents(['click']);
expect(container.querySelector('#todos').innerHTML).toEqual(
@ -917,12 +917,12 @@ describe('render', () => {
})();
};
const RowList = props => {
return $$createComponent(For, {
return $$runComponent(For, {
get each() {
return props.list;
},
children: item =>
$$createComponent(Row, {
$$runComponent(Row, {
item: item,
}),
});
@ -931,7 +931,7 @@ describe('render', () => {
(() => {
const _el$3 = $tmpl_2(),
_el$4 = _el$3.firstChild;
$$addEventListener(_el$4, 'click', props.cb, true);
$$on(_el$4, 'click', props.cb, true);
$$insert(_el$4, () => props.title);
watch(() => $$setAttribute(_el$4, 'id', props.id));
return _el$3;
@ -966,7 +966,7 @@ describe('render', () => {
_el$12 = _el$11.firstChild;
$$insert(
_el$10,
$$createComponent(Button, {
$$runComponent(Button, {
id: 'run',
title: 'Create 1,000 rows',
cb: run,
@ -974,7 +974,7 @@ describe('render', () => {
);
$$insert(
_el$12,
$$createComponent(RowList, {
$$runComponent(RowList, {
get list() {
return state.list;
},
@ -983,7 +983,7 @@ describe('render', () => {
return _el$5;
})();
};
render(() => $$createComponent(Main, {}), container);
render(() => $$runComponent(Main, {}), container);
$$delegateEvents(['click']);
expect(container.querySelector('#tbody').innerHTML).toEqual(