vite-plugin-taro-runtime 0.7.13 → 0.8.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/plugin-framework-react/runtime.js +3 -3
- package/dist/plugin-html/html-elements.d.ts +4 -0
- package/dist/plugin-html/html-elements.js +94 -0
- package/dist/plugin-html/runtime.js +1 -12
- package/dist/react/index.d.ts +3 -1
- package/dist/react/react.esm.js +56 -48
- package/dist/react/renderer-host.d.ts +4 -0
- package/dist/runtime/dom/element.d.ts +21 -3
- package/dist/runtime/dom/element.js +58 -29
- package/dist/runtime/dom/event-source.js +5 -1
- package/dist/runtime/dom/event-target.d.ts +11 -1
- package/dist/runtime/dom/event-target.js +35 -7
- package/dist/runtime/dom/event.d.ts +8 -1
- package/dist/runtime/dom/event.js +45 -14
- package/dist/runtime/dom/nearest-ctx.d.ts +3 -1
- package/dist/runtime/dom/nearest-ctx.js +10 -1
- package/dist/runtime/dom/node.d.ts +15 -7
- package/dist/runtime/dom/node.js +88 -44
- package/dist/runtime/dom/style.d.ts +7 -2
- package/dist/runtime/dom/style.js +19 -5
- package/dist/runtime/dom/text.d.ts +3 -2
- package/dist/runtime/dom/text.js +13 -6
- package/dist/runtime/dom-external/mutation-observer/implements.d.ts +3 -1
- package/dist/runtime/dom-external/mutation-observer/implements.js +5 -1
- package/dist/runtime/dom-external/mutation-observer/index.d.ts +2 -0
- package/dist/runtime/dom-external/mutation-observer/index.js +5 -1
- package/dist/runtime/dom-external/node.js +56 -18
- package/dist/runtime/dsl/common.d.ts +1 -0
- package/dist/runtime/dsl/common.js +22 -74
- package/dist/runtime/dsl/instance.d.ts +2 -3
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +1 -1
- package/dist/runtime/utils/index.js +1 -1
- package/package.json +7 -1
- package/types/tt-document.d.ts +21 -2
package/README.md
CHANGED
|
@@ -14,6 +14,8 @@ Output directories and exports mirror the upstream Taro package names (`runtime`
|
|
|
14
14
|
|
|
15
15
|
The `api`, `taro`, `components`, `router`, and `taro-h5` directories retain the runtime files and declarations used by VPT. Alternate bundles and the components' unused lazy-loader JavaScript are omitted. The generic Taro facade retains its CommonJS package boundary, shared mutable API object, and bulk native initialization. VPT's Mini facade attaches framework hooks to that same object; it does not generate a separate API inventory or promise per-API tree-shaking. H5 instead uses a read-only ESM namespace over its modular APIs and static framework hooks. The framework runtime retains Taro's original hook registration, so hooks remain grouped rather than being individually tree-shaken. Copied declarations redirect imports and module augmentations to this package's type exports, so consumer type checking does not depend on Vite aliases or upstream development dependencies. CSS remains side-effectful, and required third-party runtime dependencies are declared directly. None of these upstream Taro packages—and therefore none of their `@tarojs/helper` compiler dependencies—are installed in consumer projects.
|
|
16
16
|
|
|
17
|
+
The `plugin-html/runtime` entry installs upstream HTML hooks. Its side-effect-free `plugin-html/html-elements` companion shares the inline/block classifications and semantic `h5-*` class handling with native DOM hosts.
|
|
18
|
+
|
|
17
19
|
## Development
|
|
18
20
|
|
|
19
21
|
Build the runtime package from the repository root:
|
|
@@ -250,7 +250,7 @@ function connectReactPage(R, id) {
|
|
|
250
250
|
return h$1('div', { id, className: 'taro_page' }, children);
|
|
251
251
|
}
|
|
252
252
|
else {
|
|
253
|
-
return h$1(
|
|
253
|
+
return h$1(ReactDOM$1.getPageRootType(id), { id }, children);
|
|
254
254
|
}
|
|
255
255
|
}
|
|
256
256
|
};
|
|
@@ -636,7 +636,7 @@ function createNativePageConfig(Component, pageName, data, react, reactDOM, page
|
|
|
636
636
|
}
|
|
637
637
|
const pageObj = {
|
|
638
638
|
options: pageConfig,
|
|
639
|
-
[ONLOAD](options
|
|
639
|
+
[ONLOAD](options) {
|
|
640
640
|
hasLoaded = new Promise(resolve => { loadResolver = resolve; });
|
|
641
641
|
Current.page = this;
|
|
642
642
|
this.config = pageConfig || {};
|
|
@@ -655,7 +655,7 @@ function createNativePageConfig(Component, pageName, data, react, reactDOM, page
|
|
|
655
655
|
safeExecute($taroPath, ONLOAD, this.$taroParams);
|
|
656
656
|
loadResolver();
|
|
657
657
|
pageElement.ctx = this;
|
|
658
|
-
pageElement.performUpdate(true
|
|
658
|
+
pageElement.performUpdate(true);
|
|
659
659
|
};
|
|
660
660
|
const mount = () => {
|
|
661
661
|
if (!Current.app) {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Upstream HTML classifications shared by templates and native DOM hosts. */
|
|
2
|
+
export declare const inlineElements: ReadonlySet<string>
|
|
3
|
+
export declare const blockElements: ReadonlySet<string>
|
|
4
|
+
export declare function ensureHtmlClass(tagName: string, className: string | undefined): string
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// Upstream HTML display defaults shared by VPT's template and native DOM hosts.
|
|
2
|
+
export const inlineElements = new Set([
|
|
3
|
+
'i',
|
|
4
|
+
'abbr',
|
|
5
|
+
'select',
|
|
6
|
+
'acronym',
|
|
7
|
+
'small',
|
|
8
|
+
'bdi',
|
|
9
|
+
'kbd',
|
|
10
|
+
'strong',
|
|
11
|
+
'big',
|
|
12
|
+
'sub',
|
|
13
|
+
'sup',
|
|
14
|
+
'br',
|
|
15
|
+
'mark',
|
|
16
|
+
'meter',
|
|
17
|
+
'template',
|
|
18
|
+
'cite',
|
|
19
|
+
'object',
|
|
20
|
+
'time',
|
|
21
|
+
'code',
|
|
22
|
+
'output',
|
|
23
|
+
'u',
|
|
24
|
+
'data',
|
|
25
|
+
'picture',
|
|
26
|
+
'tt',
|
|
27
|
+
'datalist',
|
|
28
|
+
'var',
|
|
29
|
+
'dfn',
|
|
30
|
+
'del',
|
|
31
|
+
'q',
|
|
32
|
+
'em',
|
|
33
|
+
's',
|
|
34
|
+
'embed',
|
|
35
|
+
'samp',
|
|
36
|
+
'b'
|
|
37
|
+
])
|
|
38
|
+
export const blockElements = new Set([
|
|
39
|
+
'body',
|
|
40
|
+
'svg',
|
|
41
|
+
'address',
|
|
42
|
+
'fieldset',
|
|
43
|
+
'li',
|
|
44
|
+
'span',
|
|
45
|
+
'article',
|
|
46
|
+
'figcaption',
|
|
47
|
+
'main',
|
|
48
|
+
'aside',
|
|
49
|
+
'figure',
|
|
50
|
+
'nav',
|
|
51
|
+
'blockquote',
|
|
52
|
+
'footer',
|
|
53
|
+
'ol',
|
|
54
|
+
'details',
|
|
55
|
+
'p',
|
|
56
|
+
'dialog',
|
|
57
|
+
'h1',
|
|
58
|
+
'h2',
|
|
59
|
+
'h3',
|
|
60
|
+
'h4',
|
|
61
|
+
'h5',
|
|
62
|
+
'h6',
|
|
63
|
+
'pre',
|
|
64
|
+
'dd',
|
|
65
|
+
'header',
|
|
66
|
+
'section',
|
|
67
|
+
'div',
|
|
68
|
+
'hgroup',
|
|
69
|
+
'table',
|
|
70
|
+
'dl',
|
|
71
|
+
'hr',
|
|
72
|
+
'ul',
|
|
73
|
+
'dt',
|
|
74
|
+
'view',
|
|
75
|
+
'view-block'
|
|
76
|
+
])
|
|
77
|
+
|
|
78
|
+
export function ensureHtmlClass(tagName, className) {
|
|
79
|
+
const htmlClass = `h5-${tagName}`
|
|
80
|
+
const prefix = `${htmlClass} `
|
|
81
|
+
if (className === undefined || className === '') {
|
|
82
|
+
return prefix
|
|
83
|
+
}
|
|
84
|
+
// Taro uses literal-space token boundaries and preserves the caller's whitespace.
|
|
85
|
+
if (
|
|
86
|
+
className === htmlClass ||
|
|
87
|
+
className.startsWith(prefix) ||
|
|
88
|
+
className.endsWith(` ${htmlClass}`) ||
|
|
89
|
+
className.includes(` ${prefix}`)
|
|
90
|
+
) {
|
|
91
|
+
return className
|
|
92
|
+
}
|
|
93
|
+
return prefix + className
|
|
94
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isHasExtractProp } from '@tarojs/runtime';
|
|
2
2
|
import { isString, isFunction, toCamelCase, hooks, warn } from '@tarojs/shared';
|
|
3
|
+
import { inlineElements, blockElements, ensureHtmlClass } from './html-elements.js';
|
|
3
4
|
|
|
4
5
|
function genAttrMapFnFromDir(dir) {
|
|
5
6
|
const fn = function (key, value) {
|
|
@@ -18,10 +19,6 @@ function genAttrMapFnFromDir(dir) {
|
|
|
18
19
|
};
|
|
19
20
|
return fn;
|
|
20
21
|
}
|
|
21
|
-
// Taro normally fills this set by rewriting runtime.js from its compiler plugin.
|
|
22
|
-
// VPT pins the upstream defaults at install time instead: no CLI, Babel, or per-build file mutation.
|
|
23
|
-
const inlineElements = new Set(['i', 'abbr', 'select', 'acronym', 'small', 'bdi', 'kbd', 'strong', 'big', 'sub', 'sup', 'br', 'mark', 'meter', 'template', 'cite', 'object', 'time', 'code', 'output', 'u', 'data', 'picture', 'tt', 'datalist', 'var', 'dfn', 'del', 'q', 'em', 's', 'embed', 'samp', 'b']);
|
|
24
|
-
const blockElements = new Set(['body', 'svg', 'address', 'fieldset', 'li', 'span', 'article', 'figcaption', 'main', 'aside', 'figure', 'nav', 'blockquote', 'footer', 'ol', 'details', 'p', 'dialog', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'pre', 'dd', 'header', 'section', 'div', 'hgroup', 'table', 'dl', 'hr', 'ul', 'dt', 'view', 'view-block']);
|
|
25
22
|
const specialElements = new Map([
|
|
26
23
|
['slot', 'slot'],
|
|
27
24
|
['form', 'form'],
|
|
@@ -193,14 +190,6 @@ function mapNameByContion(nodeName, key, element, componentsAlias) {
|
|
|
193
190
|
});
|
|
194
191
|
}
|
|
195
192
|
}
|
|
196
|
-
function ensureHtmlClass(tagName, className = '') {
|
|
197
|
-
const classList = className.split(' ');
|
|
198
|
-
const htmlClass = `h5-${tagName}`;
|
|
199
|
-
if (classList.indexOf(htmlClass) === -1) {
|
|
200
|
-
classList.unshift(htmlClass);
|
|
201
|
-
}
|
|
202
|
-
return classList.join(' ');
|
|
203
|
-
}
|
|
204
193
|
function ensureRect(props, style = '') {
|
|
205
194
|
let cssText = style;
|
|
206
195
|
const { width, height } = props;
|
package/dist/react/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { internalInstanceKey } from './constant';
|
|
|
2
2
|
import { createRoot } from './render';
|
|
3
3
|
import type { TaroElement } from 'vite-plugin-taro-runtime/runtime/mini';
|
|
4
4
|
import type { ReactNode } from 'react';
|
|
5
|
+
declare function getPageRootType(id: string): string;
|
|
5
6
|
declare const unstable_batchedUpdates: (fn: any, a: any) => any;
|
|
6
7
|
declare function unmountComponentAtNode(dom: TaroElement): boolean;
|
|
7
8
|
declare function createPortal(children: ReactNode, containerInfo: TaroElement, key?: string): {
|
|
@@ -16,13 +17,14 @@ declare const flushSync: {
|
|
|
16
17
|
<R>(fn: () => R): R;
|
|
17
18
|
};
|
|
18
19
|
export type { RendererHost } from './renderer-host';
|
|
19
|
-
export { createPortal, createRoot, flushSync, internalInstanceKey, unmountComponentAtNode, unstable_batchedUpdates };
|
|
20
|
+
export { createPortal, createRoot, flushSync, getPageRootType, internalInstanceKey, unmountComponentAtNode, unstable_batchedUpdates };
|
|
20
21
|
declare const _default: {
|
|
21
22
|
flushSync: {
|
|
22
23
|
(): void;
|
|
23
24
|
<R>(fn: () => R): R;
|
|
24
25
|
};
|
|
25
26
|
createRoot: typeof createRoot;
|
|
27
|
+
getPageRootType: typeof getPageRootType;
|
|
26
28
|
unstable_batchedUpdates: (fn: any, a: any) => any;
|
|
27
29
|
unmountComponentAtNode: typeof unmountComponentAtNode;
|
|
28
30
|
createPortal: typeof createPortal;
|
package/dist/react/react.esm.js
CHANGED
|
@@ -403,8 +403,9 @@ function setEvent(dom, name, value, oldValue) {
|
|
|
403
403
|
}
|
|
404
404
|
if (isFunction(value)) {
|
|
405
405
|
if (oldValue) {
|
|
406
|
-
|
|
406
|
+
// Keep the host subscription active while replacing the logical callback.
|
|
407
407
|
dom.addEventListener(eventName, value, process.env.TARO_PLATFORM !== PLATFORM_TYPE.HARMONY ? { isCapture, sideEffect: false } : undefined);
|
|
408
|
+
dom.removeEventListener(eventName, oldValue, process.env.TARO_PLATFORM !== PLATFORM_TYPE.HARMONY ? false : undefined);
|
|
408
409
|
}
|
|
409
410
|
else {
|
|
410
411
|
dom.addEventListener(eventName, value, process.env.TARO_PLATFORM !== PLATFORM_TYPE.HARMONY ? isCapture : undefined);
|
|
@@ -495,63 +496,66 @@ function setHarmonyStyle(dom, value, oldValue) {
|
|
|
495
496
|
}
|
|
496
497
|
dom.setAttribute('__hmStyle', value);
|
|
497
498
|
}
|
|
498
|
-
function
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
499
|
+
function setStyleProperty(dom, value, oldValue) {
|
|
500
|
+
if (process.env.TARO_ENV === 'tt' && isEnableTTDom()) {
|
|
501
|
+
if (isString(value)) {
|
|
502
|
+
dom.setAttribute('style', value);
|
|
503
|
+
}
|
|
504
|
+
else if (isObject(value)) {
|
|
505
|
+
dom.setAttribute('style', styleObjectToCss(value));
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
else {
|
|
509
|
+
if (/harmony.*cpp/.test(process.env.TARO_ENV || '')) {
|
|
510
|
+
return dom.setAttribute('_style4cpp', value);
|
|
511
|
+
}
|
|
512
|
+
const style = dom.style;
|
|
513
|
+
if (isString(value)) {
|
|
514
|
+
style.cssText = value;
|
|
512
515
|
}
|
|
513
516
|
else {
|
|
514
|
-
if (
|
|
515
|
-
|
|
517
|
+
if (isString(oldValue)) {
|
|
518
|
+
style.cssText = '';
|
|
519
|
+
oldValue = null;
|
|
516
520
|
}
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
oldValue = null;
|
|
525
|
-
}
|
|
526
|
-
if (isObject(oldValue)) {
|
|
527
|
-
for (const i in oldValue) {
|
|
528
|
-
if (!(value && i in value)) {
|
|
529
|
-
// Harmony特殊处理
|
|
530
|
-
if (process.env.TARO_PLATFORM === PLATFORM_TYPE.HARMONY && i === 'position' && oldValue[i] === 'fixed') {
|
|
531
|
-
// @ts-ignore
|
|
532
|
-
dom.setLayer(0);
|
|
533
|
-
}
|
|
534
|
-
setStyle(style, i, '');
|
|
521
|
+
if (isObject(oldValue)) {
|
|
522
|
+
for (const i in oldValue) {
|
|
523
|
+
if (!(value && i in value)) {
|
|
524
|
+
// Harmony特殊处理
|
|
525
|
+
if (process.env.TARO_PLATFORM === PLATFORM_TYPE.HARMONY && i === 'position' && oldValue[i] === 'fixed') {
|
|
526
|
+
// @ts-ignore
|
|
527
|
+
dom.setLayer(0);
|
|
535
528
|
}
|
|
529
|
+
setStyle(style, i, '');
|
|
536
530
|
}
|
|
537
531
|
}
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
532
|
+
}
|
|
533
|
+
if (isObject(value)) {
|
|
534
|
+
for (const i in value) {
|
|
535
|
+
if (!oldValue || !isEqual(value[i], oldValue[i])) {
|
|
536
|
+
// Harmony特殊处理
|
|
537
|
+
if (process.env.TARO_PLATFORM === PLATFORM_TYPE.HARMONY && i === 'position') {
|
|
538
|
+
if (value[i] === 'fixed' || (value[i] !== 'fixed' && (oldValue === null || oldValue === void 0 ? void 0 : oldValue[i]))) {
|
|
539
|
+
// @ts-ignore
|
|
540
|
+
dom.setLayer(value[i] === 'fixed' ? 1 : 0);
|
|
547
541
|
}
|
|
548
|
-
setStyle(style, i, value[i]);
|
|
549
542
|
}
|
|
543
|
+
setStyle(style, i, value[i]);
|
|
550
544
|
}
|
|
551
545
|
}
|
|
552
546
|
}
|
|
553
547
|
}
|
|
554
548
|
}
|
|
549
|
+
}
|
|
550
|
+
function setProperty(dom, name, value, oldValue) {
|
|
551
|
+
var _a, _b;
|
|
552
|
+
name = name === 'className' ? 'class' : name;
|
|
553
|
+
if (name === 'key' ||
|
|
554
|
+
name === 'children' ||
|
|
555
|
+
name === 'ref') ;
|
|
556
|
+
else if (name === 'style') {
|
|
557
|
+
host.batchStyleUpdate(dom, () => setStyleProperty(dom, value, oldValue))
|
|
558
|
+
}
|
|
555
559
|
else if (isEventName(name)) {
|
|
556
560
|
setEvent(dom, name, value, oldValue);
|
|
557
561
|
}
|
|
@@ -658,8 +662,8 @@ const hostConfig = {
|
|
|
658
662
|
getRootHostContext() {
|
|
659
663
|
return {};
|
|
660
664
|
},
|
|
661
|
-
getChildHostContext(parentHostContext) {
|
|
662
|
-
return parentHostContext;
|
|
665
|
+
getChildHostContext(parentHostContext, type) {
|
|
666
|
+
return host.getChildHostContext(parentHostContext, type);
|
|
663
667
|
},
|
|
664
668
|
prepareForCommit(container) {
|
|
665
669
|
host.beforeCommit?.(container);
|
|
@@ -995,14 +999,18 @@ function createPortal(children, containerInfo, key) {
|
|
|
995
999
|
}
|
|
996
1000
|
// Public flushSync runs a callback at synchronous priority; controlled-input restoration only flushes queued sync work.
|
|
997
1001
|
const flushSync = TaroReconciler.flushSyncFromReconciler;
|
|
1002
|
+
function getPageRootType(id) {
|
|
1003
|
+
return host.getPageRootType(id);
|
|
1004
|
+
}
|
|
998
1005
|
var index = {
|
|
999
1006
|
flushSync,
|
|
1000
1007
|
createRoot,
|
|
1008
|
+
getPageRootType,
|
|
1001
1009
|
unstable_batchedUpdates,
|
|
1002
1010
|
unmountComponentAtNode,
|
|
1003
1011
|
createPortal,
|
|
1004
1012
|
internalInstanceKey
|
|
1005
1013
|
};
|
|
1006
1014
|
|
|
1007
|
-
export { createPortal, createRoot, index as default, flushSync, internalInstanceKey, unmountComponentAtNode, unstable_batchedUpdates };
|
|
1015
|
+
export { createPortal, createRoot, index as default, flushSync, getPageRootType, internalInstanceKey, unmountComponentAtNode, unstable_batchedUpdates };
|
|
1008
1016
|
//# sourceMappingURL=react.esm.js.map
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
/** Host-owned creation, form classification and commit boundaries for the shared React renderer. */
|
|
2
2
|
export type RendererHost<Container, Context, Element, Text> = Readonly<{
|
|
3
|
+
getPageRootType(id: string): string
|
|
4
|
+
getChildHostContext(parentContext: Context, type: string): Context
|
|
3
5
|
createElement(container: Container, context: Context, type: string): Element
|
|
4
6
|
createText(container: Container, context: Context, text: string): Text
|
|
5
7
|
isFormElement(element: Element): boolean
|
|
8
|
+
/** Synchronously scope one style-prop application; logical setters and mutation records still run. */
|
|
9
|
+
batchStyleUpdate(element: Element, update: () => void): void
|
|
6
10
|
beforeCommit?(container: Container): void
|
|
7
11
|
afterCommit(container: Container): void
|
|
8
12
|
}>
|
|
@@ -9,11 +9,13 @@ declare class TaroElement extends TaroNode {
|
|
|
9
9
|
ctx?: any;
|
|
10
10
|
tagName: string;
|
|
11
11
|
props: Record<string, any>;
|
|
12
|
-
|
|
12
|
+
private _style?: Style;
|
|
13
13
|
dataset: Record<string, unknown>;
|
|
14
14
|
innerHTML: string;
|
|
15
15
|
constructor();
|
|
16
16
|
private _stopPropagation;
|
|
17
|
+
get style(): Style;
|
|
18
|
+
set style(value: Style);
|
|
17
19
|
get id(): string;
|
|
18
20
|
set id(val: string);
|
|
19
21
|
get className(): string;
|
|
@@ -29,11 +31,21 @@ declare class TaroElement extends TaroNode {
|
|
|
29
31
|
get focus(): () => void;
|
|
30
32
|
set focus(value: () => void);
|
|
31
33
|
blur(): void;
|
|
34
|
+
/** Pre-mutation template classification: pure view for writes, static view for removals. Native hosts return false. */
|
|
35
|
+
prepareAttributeMutation(removing: boolean): boolean;
|
|
32
36
|
setAttribute(qualifiedName: string, value: any): void;
|
|
33
|
-
/**
|
|
37
|
+
/**
|
|
38
|
+
* 逻辑属性、ID/dataset 和 mutation 记录更新后调用,尚未转换模板属性别名。
|
|
39
|
+
* value 为逻辑分支处理后的属性值,isPureView 记录修改前的模板分类。
|
|
40
|
+
* style 属性先触发 Style 委托,再进入此入口;默认准备模板属性及类型更新。
|
|
41
|
+
*/
|
|
34
42
|
delegateAttributeUpdate(qualifiedName: string, value: unknown, isPureView: boolean): void;
|
|
35
43
|
removeAttribute(qualifiedName: string): void;
|
|
36
|
-
/**
|
|
44
|
+
/**
|
|
45
|
+
* 逻辑移除完成后调用,isStaticView 记录移除前的模板分类。
|
|
46
|
+
* 普通属性缺失或被 hook 拦截时提前返回;style 先经 Style 委托清空。
|
|
47
|
+
* 默认准备模板属性及类型更新,host 可接管原生属性移除。
|
|
48
|
+
*/
|
|
37
49
|
delegateAttributeRemoval(qualifiedName: string, isStaticView: boolean): void;
|
|
38
50
|
getAttribute(qualifiedName: string): string;
|
|
39
51
|
getElementsByTagName(tagName: string): TaroElement[];
|
|
@@ -41,6 +53,12 @@ declare class TaroElement extends TaroNode {
|
|
|
41
53
|
dispatchEvent(event: TaroEvent): boolean;
|
|
42
54
|
addEventListener(type: any, handler: any, options: any): void;
|
|
43
55
|
removeEventListener(type: any, handler: any, sideEffect?: boolean): void;
|
|
56
|
+
/**
|
|
57
|
+
* added=true 在添加处理器前调用,false 在移除后调用,负责模板节点类型副作用。
|
|
58
|
+
* sideEffect=false 只抑制模板更新;原生订阅通知由 delegateEventListener 独立处理。
|
|
59
|
+
* 默认实现按 added 选择上游添加/移除 hook,并按需查询组件别名。
|
|
60
|
+
*/
|
|
61
|
+
delegateEventUpdate(added: boolean, sideEffect: boolean): void;
|
|
44
62
|
static extend(methodName: string, options: TFunc | Record<string, any>): void;
|
|
45
63
|
}
|
|
46
64
|
|
|
@@ -14,7 +14,6 @@ class TaroElement extends TaroNode {
|
|
|
14
14
|
this.props = {};
|
|
15
15
|
this.dataset = EMPTY_OBJ;
|
|
16
16
|
this.nodeType = 1 /* NodeType.ELEMENT_NODE */;
|
|
17
|
-
this.style = new Style(this);
|
|
18
17
|
hooks.call('patchElement', this);
|
|
19
18
|
}
|
|
20
19
|
_stopPropagation(event) {
|
|
@@ -22,7 +21,7 @@ class TaroElement extends TaroNode {
|
|
|
22
21
|
let target = this;
|
|
23
22
|
// eslint-disable-next-line no-cond-assign
|
|
24
23
|
while ((target = target.parentNode)) {
|
|
25
|
-
const listeners = target.
|
|
24
|
+
const listeners = target.getEventHandlers(event.type);
|
|
26
25
|
if (!isArray(listeners)) {
|
|
27
26
|
continue;
|
|
28
27
|
}
|
|
@@ -32,6 +31,13 @@ class TaroElement extends TaroNode {
|
|
|
32
31
|
}
|
|
33
32
|
}
|
|
34
33
|
}
|
|
34
|
+
// Each element retains one mutable declaration, initialized on first style access.
|
|
35
|
+
get style() {
|
|
36
|
+
return this._style ??= new Style(this);
|
|
37
|
+
}
|
|
38
|
+
set style(value) {
|
|
39
|
+
this._style = value;
|
|
40
|
+
}
|
|
35
41
|
get id() {
|
|
36
42
|
return this.getAttribute(ID);
|
|
37
43
|
}
|
|
@@ -56,7 +62,7 @@ class TaroElement extends TaroNode {
|
|
|
56
62
|
get attributes() {
|
|
57
63
|
const props = this.props;
|
|
58
64
|
const propKeys = Object.keys(props);
|
|
59
|
-
const style = this.
|
|
65
|
+
const style = this.getAttribute(STYLE);
|
|
60
66
|
const attrs = propKeys.map(key => ({ name: key, value: props[key] }));
|
|
61
67
|
return attrs.concat(style ? { name: STYLE, value: style } : []);
|
|
62
68
|
}
|
|
@@ -89,10 +95,14 @@ class TaroElement extends TaroNode {
|
|
|
89
95
|
blur() {
|
|
90
96
|
this.setAttribute(FOCUS, false);
|
|
91
97
|
}
|
|
98
|
+
/** Capture template classification before logical mutation, observer records and removal hooks. */
|
|
99
|
+
prepareAttributeMutation(removing) {
|
|
100
|
+
return this.nodeName === VIEW && isHasExtractProp(this) === removing && !this.isAnyEventBinded();
|
|
101
|
+
}
|
|
92
102
|
setAttribute(qualifiedName, value) {
|
|
93
103
|
process.env.NODE_ENV !== 'production' && warn(isString(value) && value.length > PROPERTY_THRESHOLD, `元素 ${this.nodeName} 的 ${qualifiedName} 属性值数据量过大,可能会影响渲染性能。考虑降低图片转为 base64 的阈值或在 CSS 中使用 base64。`);
|
|
94
|
-
const isPureView = this.
|
|
95
|
-
if (qualifiedName !== STYLE) {
|
|
104
|
+
const isPureView = this.prepareAttributeMutation(false);
|
|
105
|
+
if (qualifiedName !== STYLE && MutationObserver.hasObservers) {
|
|
96
106
|
MutationObserver.record({
|
|
97
107
|
target: this,
|
|
98
108
|
type: "attributes" /* MutationRecordType.ATTRIBUTES */,
|
|
@@ -126,7 +136,15 @@ class TaroElement extends TaroNode {
|
|
|
126
136
|
}
|
|
127
137
|
this.delegateAttributeUpdate(qualifiedName, value, isPureView);
|
|
128
138
|
}
|
|
129
|
-
/**
|
|
139
|
+
/**
|
|
140
|
+
* Taro 已完成逻辑属性写入、相应的 ID/dataset 更新及 mutation 记录,再通知 host。
|
|
141
|
+
* qualifiedName 保留属性名;value 是逻辑分支处理后的值,例如 id 已转为字符串,
|
|
142
|
+
* 此时尚未执行模板短名/组件别名转换。
|
|
143
|
+
* isPureView 保存修改前的模板分类,用于判断属性变化是否要求切换模板节点类型。
|
|
144
|
+
* 默认实现为已挂载节点准备属性和节点类型 payload;host 可接管原生属性写入。
|
|
145
|
+
* style 属性会先经 Style.delegateStyleUpdate,再进入此处;host 应按属性名
|
|
146
|
+
* 区分这两个通知的职责,复用 Style 已完成的逻辑样式处理。
|
|
147
|
+
*/
|
|
130
148
|
delegateAttributeUpdate(qualifiedName, value, isPureView) {
|
|
131
149
|
// Serialization
|
|
132
150
|
if (!this._root)
|
|
@@ -169,13 +187,15 @@ class TaroElement extends TaroNode {
|
|
|
169
187
|
}
|
|
170
188
|
}
|
|
171
189
|
removeAttribute(qualifiedName) {
|
|
172
|
-
const isStaticView = this.
|
|
173
|
-
MutationObserver.
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
190
|
+
const isStaticView = this.prepareAttributeMutation(true);
|
|
191
|
+
if (MutationObserver.hasObservers) {
|
|
192
|
+
MutationObserver.record({
|
|
193
|
+
target: this,
|
|
194
|
+
type: "attributes" /* MutationRecordType.ATTRIBUTES */,
|
|
195
|
+
attributeName: qualifiedName,
|
|
196
|
+
oldValue: this.getAttribute(qualifiedName)
|
|
197
|
+
});
|
|
198
|
+
}
|
|
179
199
|
if (qualifiedName === STYLE) {
|
|
180
200
|
this.style.cssText = '';
|
|
181
201
|
}
|
|
@@ -191,7 +211,13 @@ class TaroElement extends TaroNode {
|
|
|
191
211
|
}
|
|
192
212
|
this.delegateAttributeRemoval(qualifiedName, isStaticView);
|
|
193
213
|
}
|
|
194
|
-
/**
|
|
214
|
+
/**
|
|
215
|
+
* Taro 执行原有属性移除逻辑后通知 host;普通属性不存在或被移除 hook 拦截时提前返回。
|
|
216
|
+
* qualifiedName 是被移除的属性名,isStaticView 保存移除前的模板分类。
|
|
217
|
+
* 默认实现准备属性清空及相应的模板类型更新;原生 host 接管原生属性移除。
|
|
218
|
+
* style 的清空先经过 Style.delegateStyleUpdate,再通知此方法,与设置 style 的顺序一致。
|
|
219
|
+
* 逻辑 props、移除拦截和 mutation 记录仍由 Taro 的公开方法维护。
|
|
220
|
+
*/
|
|
195
221
|
delegateAttributeRemoval(qualifiedName, isStaticView) {
|
|
196
222
|
// Serialization
|
|
197
223
|
if (!this._root)
|
|
@@ -233,7 +259,7 @@ class TaroElement extends TaroNode {
|
|
|
233
259
|
}
|
|
234
260
|
}
|
|
235
261
|
getAttribute(qualifiedName) {
|
|
236
|
-
const attr = qualifiedName === STYLE ? this.
|
|
262
|
+
const attr = qualifiedName === STYLE ? this._style?.cssText : this.props[qualifiedName];
|
|
237
263
|
return attr !== null && attr !== void 0 ? attr : '';
|
|
238
264
|
}
|
|
239
265
|
getElementsByTagName(tagName) {
|
|
@@ -250,7 +276,7 @@ class TaroElement extends TaroNode {
|
|
|
250
276
|
}
|
|
251
277
|
dispatchEvent(event) {
|
|
252
278
|
const cancelable = event.cancelable;
|
|
253
|
-
const listeners = this.
|
|
279
|
+
const listeners = this.getEventHandlers(event.type);
|
|
254
280
|
if (!isArray(listeners)) {
|
|
255
281
|
return false;
|
|
256
282
|
}
|
|
@@ -283,32 +309,35 @@ class TaroElement extends TaroNode {
|
|
|
283
309
|
return listeners != null;
|
|
284
310
|
}
|
|
285
311
|
addEventListener(type, handler, options) {
|
|
286
|
-
const name = this.nodeName;
|
|
287
|
-
const SPECIAL_NODES = hooks.call('getSpecialNodes');
|
|
288
312
|
let sideEffect = true;
|
|
289
313
|
if (isObject(options) && options.sideEffect === false) {
|
|
290
314
|
sideEffect = false;
|
|
291
315
|
delete options.sideEffect;
|
|
292
316
|
}
|
|
293
|
-
|
|
294
|
-
if (sideEffect !== false && !this.isAnyEventBinded() && SPECIAL_NODES.indexOf(name) > -1) {
|
|
295
|
-
const componentsAlias = getComponentsAlias();
|
|
296
|
-
const alias = componentsAlias[name]._num;
|
|
297
|
-
this.enqueueUpdate({
|
|
298
|
-
path: `${this._path}.${"nn" /* Shortcuts.NodeName */}`,
|
|
299
|
-
value: alias
|
|
300
|
-
});
|
|
301
|
-
}
|
|
317
|
+
this.delegateEventUpdate(true, sideEffect);
|
|
302
318
|
super.addEventListener(type, handler, options);
|
|
303
319
|
}
|
|
304
320
|
removeEventListener(type, handler, sideEffect = true) {
|
|
305
321
|
super.removeEventListener(type, handler);
|
|
322
|
+
this.delegateEventUpdate(false, sideEffect);
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* 事件监听变化对应的模板副作用,与原生订阅开关 delegateEventListener 分开。
|
|
326
|
+
* added=true 时在添加处理器之前调用,观察旧监听数组;added=false 时在移除之后调用,
|
|
327
|
+
* 观察剩余监听数组。默认实现据此把节点切换为可交互或 pure/static 模板。
|
|
328
|
+
* sideEffect=false 只抑制模板更新,逻辑监听器变更和原生订阅通知照常执行。
|
|
329
|
+
* 原生 host 可独立替换此模板副作用;Taro 的公开方法继续负责处理器语义。
|
|
330
|
+
*/
|
|
331
|
+
delegateEventUpdate(added, sideEffect) {
|
|
306
332
|
const name = this.nodeName;
|
|
307
333
|
const SPECIAL_NODES = hooks.call('getSpecialNodes');
|
|
308
|
-
|
|
334
|
+
// 上游添加/移除方法各有一个模板扩展 hook;合并副作用实现后按 added 选择原 hook。
|
|
335
|
+
// 参数依次是当前逻辑节点、模板副作用开关和别名查询函数。函数保持延迟调用,
|
|
336
|
+
// 由 hook 按需取得组件别名;这一步处理模板类型,不注册或取消原生事件。
|
|
337
|
+
hooks.call(added ? 'modifyAddEventListener' : 'modifyRemoveEventListener', this, sideEffect, getComponentsAlias);
|
|
309
338
|
if (sideEffect !== false && !this.isAnyEventBinded() && SPECIAL_NODES.indexOf(name) > -1) {
|
|
310
339
|
const componentsAlias = getComponentsAlias();
|
|
311
|
-
const value = name === VIEW && !isHasExtractProp(this) ? PURE_VIEW : `static-${name}
|
|
340
|
+
const value = added ? name : (name === VIEW && !isHasExtractProp(this) ? PURE_VIEW : `static-${name}`);
|
|
312
341
|
const valueAlias = componentsAlias[value]._num;
|
|
313
342
|
this.enqueueUpdate({
|
|
314
343
|
path: `${this._path}.${"nn" /* Shortcuts.NodeName */}`,
|
|
@@ -8,7 +8,11 @@ class EventSource extends Map {
|
|
|
8
8
|
removeNodeTree(child) {
|
|
9
9
|
this.removeNode(child);
|
|
10
10
|
const { childNodes } = child;
|
|
11
|
-
|
|
11
|
+
const length = childNodes.length;
|
|
12
|
+
// A local index visits the existing children in sibling order.
|
|
13
|
+
for (let index = 0; index < length; index++) {
|
|
14
|
+
this.removeNodeTree(childNodes[index]);
|
|
15
|
+
}
|
|
12
16
|
}
|
|
13
17
|
}
|
|
14
18
|
const eventSource = new EventSource();
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
import { EventHandler, AddEventListenerOptions } from '../interface/event-target.js';
|
|
2
2
|
|
|
3
3
|
declare class TaroEventTarget {
|
|
4
|
-
|
|
4
|
+
private _handlers?: Record<string, EventHandler[]>;
|
|
5
|
+
get __handlers(): Record<string, EventHandler[]>;
|
|
6
|
+
set __handlers(value: Record<string, EventHandler[]>);
|
|
7
|
+
/** Read an existing event array without materializing the handler table. */
|
|
8
|
+
getEventHandlers(type: string): EventHandler[] | undefined;
|
|
5
9
|
addEventListener(type: string, handler: EventHandler, options?: boolean | AddEventListenerOptions): void;
|
|
6
10
|
removeEventListener(type: string, handler: EventHandler): void;
|
|
11
|
+
/**
|
|
12
|
+
* 首个处理器存入后 subscribed=true,末个移除后为 false;复用现有处理器数组判断。
|
|
13
|
+
* type 为小写逻辑事件名,regionchange 已展开为 begin/end;host 负责平台订阅关系。
|
|
14
|
+
* 默认实现为空,处理器、once 和移除匹配由 Taro 维护。
|
|
15
|
+
*/
|
|
16
|
+
delegateEventListener(type: string, subscribed: boolean): void;
|
|
7
17
|
isAnyEventBinded(): boolean;
|
|
8
18
|
isOnlyClickBinded(): boolean;
|
|
9
19
|
}
|