vite-plugin-taro-runtime 0.7.12-beta.1 → 0.7.13
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/dist/plugin-framework-react/runtime.js +4 -64
- package/dist/react/react.esm.js +3 -1
- package/dist/react/renderer-host.d.ts +2 -1
- package/dist/runtime/dom/element.d.ts +4 -0
- package/dist/runtime/dom/element.js +8 -0
- package/dist/runtime/dom/node.d.ts +12 -1
- package/dist/runtime/dom/node.js +64 -62
- package/dist/runtime/dom/root.js +8 -14
- package/dist/runtime/dom/style.d.ts +2 -0
- package/dist/runtime/dom/style.js +13 -12
- package/dist/runtime/dom/text.d.ts +5 -0
- package/dist/runtime/dom/text.js +8 -4
- package/package.json +7 -1
- package/types/tt-document.d.ts +38 -0
|
@@ -1,16 +1,6 @@
|
|
|
1
1
|
import { EMPTY_OBJ, isArray, isFunction, hooks, ensure, isUndefined } from '@tarojs/shared';
|
|
2
|
-
import { Current, getPageInstance, injectPageInstance, incrementId, document, perf, PAGE_INIT, CONTAINER, window, CONTEXT_ACTIONS, safeExecute, ON_HIDE, eventCenter, getOnHideEventKey, ON_SHOW, requestAnimationFrame, getOnShowEventKey, ON_READY, getOnReadyEventKey, removePageInstance, getPath, eventHandler, addLeadingSlash
|
|
2
|
+
import { Current, getPageInstance, injectPageInstance, incrementId, document, perf, PAGE_INIT, CONTAINER, window, CONTEXT_ACTIONS, safeExecute, ON_HIDE, eventCenter, getOnHideEventKey, ON_SHOW, requestAnimationFrame, getOnShowEventKey, ON_READY, getOnReadyEventKey, removePageInstance, getPath, eventHandler, addLeadingSlash } from '@tarojs/runtime';
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
* WX App-wrap flow:
|
|
6
|
-
*
|
|
7
|
-
* React still owns one root in which every Page remains an ordinary child of the singleton App. Native WX rendering,
|
|
8
|
-
* however, is driven by independent Page.setData surfaces, so App hosts above those Page roots have no scheduler of their
|
|
9
|
-
* own. The Mini Program branch below gives the App host an app.* scheduler, fans its deltas into every mounted Page, places
|
|
10
|
-
* one opaque outlet at App {children}, and seeds each new Page with the current App snapshot in its first native batch.
|
|
11
|
-
* hydrate() is needed only for that initial snapshot; the patched runtime stops traversal at the outlet so Page roots stay
|
|
12
|
-
* in the React/Taro ownership tree without being copied into app data.
|
|
13
|
-
*/
|
|
14
4
|
const reactMeta = {
|
|
15
5
|
PageContext: EMPTY_OBJ,
|
|
16
6
|
R: EMPTY_OBJ,
|
|
@@ -266,29 +256,6 @@ function connectReactPage(R, id) {
|
|
|
266
256
|
};
|
|
267
257
|
};
|
|
268
258
|
}
|
|
269
|
-
/**
|
|
270
|
-
* One App reconciliation produces one granular app.* batch, while WX stores an App mirror inside every mounted native
|
|
271
|
-
* Page. Resolve the native stack only when that batch flushes instead of maintaining a second Page registry or active-Page
|
|
272
|
-
* tracker. WeChat orders getCurrentPages() from the oldest hidden Page to the current visible Page, so forEach dispatches
|
|
273
|
-
* all hidden surfaces first. Only the final current Page receives Taro's callback: every setData call has then been issued,
|
|
274
|
-
* and Taro's scheduler completes its batch exactly once rather than coordinating one callback per Page.
|
|
275
|
-
*/
|
|
276
|
-
function broadcastAppUpdate(data, callback) {
|
|
277
|
-
const pages = getCurrentPages();
|
|
278
|
-
const currentPage = pages[pages.length - 1];
|
|
279
|
-
if (!currentPage) {
|
|
280
|
-
callback();
|
|
281
|
-
return;
|
|
282
|
-
}
|
|
283
|
-
pages.forEach(page => {
|
|
284
|
-
if (page === currentPage) {
|
|
285
|
-
page.setData(data, callback);
|
|
286
|
-
}
|
|
287
|
-
else {
|
|
288
|
-
page.setData(data);
|
|
289
|
-
}
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
259
|
/**
|
|
293
260
|
* 桥接小程序 App 构造器和 React 渲染流程
|
|
294
261
|
* @param App 用户编写的入口组件
|
|
@@ -335,21 +302,9 @@ function createReactApp(App, react, dom, config) {
|
|
|
335
302
|
container.id = appId;
|
|
336
303
|
appContainer === null || appContainer === void 0 ? void 0 : appContainer.appendChild(container);
|
|
337
304
|
}
|
|
338
|
-
/*
|
|
339
|
-
* renderReactRoot runs only for the Mini Program branch. The patched WX document makes this App container a
|
|
340
|
-
* TaroRootElement, so it serves simultaneously as React's existing host container and Taro's App scheduler; its
|
|
341
|
-
* structural _path is app and its _root is itself. Assign only the native sink that fans Taro's normal granular
|
|
342
|
-
* batches across Page surfaces. No detached scheduler node, second React root, or host-property override participates.
|
|
343
|
-
*/
|
|
344
|
-
container.ctx = { setData: broadcastAppUpdate };
|
|
345
305
|
// VPT requires React 19: both the Mini renderer and react-dom/client provide concurrent roots.
|
|
346
306
|
const root = ReactDOM$1.createRoot(container);
|
|
347
307
|
root.render(h$1(AppWrapper));
|
|
348
|
-
/*
|
|
349
|
-
* Return the exact host passed to ReactDOM. AppWrapper.mount closes over this immutable value when a Page is added,
|
|
350
|
-
* guaranteeing that its initial snapshot comes from the same singleton App tree without a host registry or lookup.
|
|
351
|
-
*/
|
|
352
|
-
return container;
|
|
353
308
|
}
|
|
354
309
|
class AppWrapper extends react.Component {
|
|
355
310
|
constructor(props) {
|
|
@@ -371,19 +326,6 @@ function createReactApp(App, react, dom, config) {
|
|
|
371
326
|
}
|
|
372
327
|
this.forceUpdate((...args) => {
|
|
373
328
|
perf.stop(PAGE_INIT);
|
|
374
|
-
if (process.env.TARO_PLATFORM !== 'web') {
|
|
375
|
-
/*
|
|
376
|
-
* React has now committed the Page root, but createPageConfig has not yet attached the native Page ctx or
|
|
377
|
-
* called performUpdate(true). Queue a lazy app.cn snapshot beside the Page root's already-pending page.*
|
|
378
|
-
* payloads. Taro therefore resolves both in one initial setData: no blank App frame, second bridge write,
|
|
379
|
-
* Page-ready phase, or custom pending queue. Patched hydrate() stops at the outlet before Page roots.
|
|
380
|
-
*/
|
|
381
|
-
const pageRoot = document.getElementById(id);
|
|
382
|
-
pageRoot.enqueueUpdate({
|
|
383
|
-
path: 'app.cn',
|
|
384
|
-
value: () => hydrate(container).cn
|
|
385
|
-
});
|
|
386
|
-
}
|
|
387
329
|
return cb(...args);
|
|
388
330
|
});
|
|
389
331
|
}
|
|
@@ -417,11 +359,9 @@ function createReactApp(App, react, dom, config) {
|
|
|
417
359
|
return h$1(App, props, children);
|
|
418
360
|
}
|
|
419
361
|
}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
*/
|
|
424
|
-
const container = process.env.TARO_PLATFORM !== 'web' ? renderReactRoot() : null;
|
|
362
|
+
if (process.env.TARO_PLATFORM !== 'web') {
|
|
363
|
+
renderReactRoot();
|
|
364
|
+
}
|
|
425
365
|
const [ONLAUNCH, ONSHOW, ONHIDE] = hooks.call('getMiniLifecycleImpl').app;
|
|
426
366
|
const appObj = Object.create({
|
|
427
367
|
render(cb) {
|
package/dist/react/react.esm.js
CHANGED
|
@@ -32,6 +32,7 @@ function getEventPriority(domEventName) {
|
|
|
32
32
|
switch (domEventName) {
|
|
33
33
|
case 'cancel':
|
|
34
34
|
case 'click':
|
|
35
|
+
case 'tap':
|
|
35
36
|
case 'close':
|
|
36
37
|
case 'contextmenu':
|
|
37
38
|
case 'copy':
|
|
@@ -660,7 +661,8 @@ const hostConfig = {
|
|
|
660
661
|
getChildHostContext(parentHostContext) {
|
|
661
662
|
return parentHostContext;
|
|
662
663
|
},
|
|
663
|
-
prepareForCommit(
|
|
664
|
+
prepareForCommit(container) {
|
|
665
|
+
host.beforeCommit?.(container);
|
|
664
666
|
return null;
|
|
665
667
|
},
|
|
666
668
|
resetAfterCommit(container) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
/** Host-owned creation, form classification and
|
|
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
3
|
createElement(container: Container, context: Context, type: string): Element
|
|
4
4
|
createText(container: Container, context: Context, text: string): Text
|
|
5
5
|
isFormElement(element: Element): boolean
|
|
6
|
+
beforeCommit?(container: Container): void
|
|
6
7
|
afterCommit(container: Container): void
|
|
7
8
|
}>
|
|
@@ -30,7 +30,11 @@ declare class TaroElement extends TaroNode {
|
|
|
30
30
|
set focus(value: () => void);
|
|
31
31
|
blur(): void;
|
|
32
32
|
setAttribute(qualifiedName: string, value: any): void;
|
|
33
|
+
/** Delegates after logical storage and ID/dataset updates; the flag records the prior template view classification. */
|
|
34
|
+
delegateAttributeUpdate(qualifiedName: string, value: unknown, isPureView: boolean): void;
|
|
33
35
|
removeAttribute(qualifiedName: string): void;
|
|
36
|
+
/** Delegates after successful logical removal; the flag records the prior template view classification. */
|
|
37
|
+
delegateAttributeRemoval(qualifiedName: string, isStaticView: boolean): void;
|
|
34
38
|
getAttribute(qualifiedName: string): string;
|
|
35
39
|
getElementsByTagName(tagName: string): TaroElement[];
|
|
36
40
|
getElementsByClassName(className: string): TaroElement[];
|
|
@@ -124,6 +124,10 @@ class TaroElement extends TaroNode {
|
|
|
124
124
|
}
|
|
125
125
|
break;
|
|
126
126
|
}
|
|
127
|
+
this.delegateAttributeUpdate(qualifiedName, value, isPureView);
|
|
128
|
+
}
|
|
129
|
+
/** Delegates the stored attribute value; isPureView preserves the pre-mutation template classification. */
|
|
130
|
+
delegateAttributeUpdate(qualifiedName, value, isPureView) {
|
|
127
131
|
// Serialization
|
|
128
132
|
if (!this._root)
|
|
129
133
|
return;
|
|
@@ -185,6 +189,10 @@ class TaroElement extends TaroNode {
|
|
|
185
189
|
}
|
|
186
190
|
delete this.props[qualifiedName];
|
|
187
191
|
}
|
|
192
|
+
this.delegateAttributeRemoval(qualifiedName, isStaticView);
|
|
193
|
+
}
|
|
194
|
+
/** Delegates a completed removal; interrupted and absent attributes retain their original early returns. */
|
|
195
|
+
delegateAttributeRemoval(qualifiedName, isStaticView) {
|
|
188
196
|
// Serialization
|
|
189
197
|
if (!this._root)
|
|
190
198
|
return;
|
|
@@ -20,7 +20,8 @@ declare class TaroNode extends TaroEventTarget {
|
|
|
20
20
|
childNodes: TaroNode[];
|
|
21
21
|
constructor();
|
|
22
22
|
private hydrate;
|
|
23
|
-
|
|
23
|
+
/** Delegates a complete child-list update, including the final reset after element textContent changes. */
|
|
24
|
+
delegateChildReset(isClean?: boolean): void;
|
|
24
25
|
private updateSingleChild;
|
|
25
26
|
get _root(): TaroRootElement | null;
|
|
26
27
|
get _scope(): MpInstance | null | undefined;
|
|
@@ -71,6 +72,16 @@ declare class TaroNode extends TaroEventTarget {
|
|
|
71
72
|
* 2. remove C
|
|
72
73
|
*/
|
|
73
74
|
removeChild<T extends TaroNode>(child: T, options?: RemoveChildOptions): T;
|
|
75
|
+
/**
|
|
76
|
+
* Delegates an insertion after Taro updates its tree, including detached parents.
|
|
77
|
+
* The index is the insertion offset when refChild is supplied. The default prepares template payloads.
|
|
78
|
+
*/
|
|
79
|
+
delegateChildInsertion(newChild: TaroNode, refChild: TaroNode | null | undefined, index: number, isReplace: boolean | undefined): void;
|
|
80
|
+
/**
|
|
81
|
+
* Delegates a removal after logical detachment and event identity cleanup.
|
|
82
|
+
* Every removal is forwarded; options.doUpdate only suppresses the default template update.
|
|
83
|
+
*/
|
|
84
|
+
delegateChildRemoval(child: TaroNode, options: RemoveChildOptions): void;
|
|
74
85
|
remove(options?: RemoveChildOptions): void;
|
|
75
86
|
hasChildNodes(): boolean;
|
|
76
87
|
enqueueUpdate(payload: UpdatePayload): void;
|
package/dist/runtime/dom/node.js
CHANGED
|
@@ -20,7 +20,8 @@ class TaroNode extends TaroEventTarget {
|
|
|
20
20
|
this.sid = this.uid; // dom 节点全局唯一 id,不可被修改
|
|
21
21
|
eventSource.set(this.sid, this);
|
|
22
22
|
}
|
|
23
|
-
|
|
23
|
+
/** Delegates a complete child-list update; the default hydrates lazily or emits an empty list. */
|
|
24
|
+
delegateChildReset(isClean) {
|
|
24
25
|
const cleanChildNodes = () => [];
|
|
25
26
|
const rerenderChildNodes = () => {
|
|
26
27
|
const childNodes = this.childNodes.filter(node => !isComment(node));
|
|
@@ -101,13 +102,13 @@ class TaroNode extends TaroEventTarget {
|
|
|
101
102
|
this.removeChild(this.firstChild, { doUpdate: false });
|
|
102
103
|
}
|
|
103
104
|
if (text === '') {
|
|
104
|
-
this.
|
|
105
|
+
this.delegateChildReset(true);
|
|
105
106
|
}
|
|
106
107
|
else {
|
|
107
108
|
const newText = env.document.createTextNode(text);
|
|
108
109
|
addedNodes.push(newText);
|
|
109
110
|
this.appendChild(newText);
|
|
110
|
-
this.
|
|
111
|
+
this.delegateChildReset();
|
|
111
112
|
}
|
|
112
113
|
// @Todo: appendChild 会多触发一次
|
|
113
114
|
MutationObserver.record({
|
|
@@ -149,52 +150,9 @@ class TaroNode extends TaroEventTarget {
|
|
|
149
150
|
// appendChild
|
|
150
151
|
this.childNodes.push(newChild);
|
|
151
152
|
}
|
|
152
|
-
|
|
153
|
-
//
|
|
154
|
-
|
|
155
|
-
if (!refChild) {
|
|
156
|
-
// appendChild
|
|
157
|
-
const isOnlyChild = childNodesLength === 1;
|
|
158
|
-
if (isOnlyChild) {
|
|
159
|
-
this.updateChildNodes();
|
|
160
|
-
}
|
|
161
|
-
else {
|
|
162
|
-
this.enqueueUpdate({
|
|
163
|
-
path: newChild._path,
|
|
164
|
-
value: this.hydrate(newChild)
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
else if (isReplace) {
|
|
169
|
-
// replaceChild
|
|
170
|
-
this.enqueueUpdate({
|
|
171
|
-
path: newChild._path,
|
|
172
|
-
value: this.hydrate(newChild)
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
else {
|
|
176
|
-
// insertBefore 有两种更新模式
|
|
177
|
-
// 比方说有 A B C 三个节点,现在要在 C 前插入 D
|
|
178
|
-
// 1. 插入 D,然后更新整个父节点的 childNodes 数组
|
|
179
|
-
// setData({ cn: [A, B, D, C] })
|
|
180
|
-
// 2. 插入 D,然后更新 D 以及 D 之后每个节点的数据
|
|
181
|
-
// setData ({
|
|
182
|
-
// cn.[2]: D,
|
|
183
|
-
// cn.[3]: C,
|
|
184
|
-
// })
|
|
185
|
-
// 由于微信解析 ’cn.[2]‘ 这些路径的时候也需要消耗时间,
|
|
186
|
-
// 所以根据 insertBefore 插入的位置来做不同的处理
|
|
187
|
-
const mark = childNodesLength * 2 / 3;
|
|
188
|
-
if (mark > index) {
|
|
189
|
-
// 如果 insertBefore 的位置在 childNodes 的 2/3 前,则为了避免解析路径消耗过多的时间,采用第一种方式
|
|
190
|
-
this.updateChildNodes();
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
// 如果 insertBefore 的位置在 childNodes 的 2/3 之后,则采用第二种方式,避免 childNodes 的全量更新
|
|
194
|
-
this.updateSingleChild(index);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
}
|
|
153
|
+
// Delegation runs after the logical insertion, including on detached parents.
|
|
154
|
+
// Its default implementation prepares template payloads; native hosts can replace it before any serialization work.
|
|
155
|
+
this.delegateChildInsertion(newChild, refChild, index, isReplace);
|
|
198
156
|
if (this._root) {
|
|
199
157
|
bumpNearestCtxEpochForRoot(this._root);
|
|
200
158
|
}
|
|
@@ -270,15 +228,68 @@ class TaroNode extends TaroEventTarget {
|
|
|
270
228
|
if (cleanRef !== false) {
|
|
271
229
|
eventSource.removeNodeTree(child);
|
|
272
230
|
}
|
|
273
|
-
//
|
|
274
|
-
|
|
275
|
-
this.updateChildNodes();
|
|
276
|
-
}
|
|
231
|
+
// Forward every removal. doUpdate controls template batching, not whether the logical child was removed.
|
|
232
|
+
this.delegateChildRemoval(child, options);
|
|
277
233
|
if (this._root) {
|
|
278
234
|
bumpNearestCtxEpochForRoot(this._root);
|
|
279
235
|
}
|
|
280
236
|
return child;
|
|
281
237
|
}
|
|
238
|
+
/** Delegates an insertion after Taro has updated parentNode and childNodes. */
|
|
239
|
+
delegateChildInsertion(newChild, refChild, index, isReplace) {
|
|
240
|
+
const childNodesLength = this.childNodes.length;
|
|
241
|
+
// Serialization
|
|
242
|
+
if (this._root) {
|
|
243
|
+
if (!refChild) {
|
|
244
|
+
// appendChild
|
|
245
|
+
const isOnlyChild = childNodesLength === 1;
|
|
246
|
+
if (isOnlyChild) {
|
|
247
|
+
this.delegateChildReset();
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
this.enqueueUpdate({
|
|
251
|
+
path: newChild._path,
|
|
252
|
+
value: this.hydrate(newChild)
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
else if (isReplace) {
|
|
257
|
+
// replaceChild
|
|
258
|
+
this.enqueueUpdate({
|
|
259
|
+
path: newChild._path,
|
|
260
|
+
value: this.hydrate(newChild)
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
// insertBefore 有两种更新模式
|
|
265
|
+
// 比方说有 A B C 三个节点,现在要在 C 前插入 D
|
|
266
|
+
// 1. 插入 D,然后更新整个父节点的 childNodes 数组
|
|
267
|
+
// setData({ cn: [A, B, D, C] })
|
|
268
|
+
// 2. 插入 D,然后更新 D 以及 D 之后每个节点的数据
|
|
269
|
+
// setData ({
|
|
270
|
+
// cn.[2]: D,
|
|
271
|
+
// cn.[3]: C,
|
|
272
|
+
// })
|
|
273
|
+
// 由于微信解析 ’cn.[2]‘ 这些路径的时候也需要消耗时间,
|
|
274
|
+
// 所以根据 insertBefore 插入的位置来做不同的处理
|
|
275
|
+
const mark = childNodesLength * 2 / 3;
|
|
276
|
+
if (mark > index) {
|
|
277
|
+
// 如果 insertBefore 的位置在 childNodes 的 2/3 前,则为了避免解析路径消耗过多的时间,采用第一种方式
|
|
278
|
+
this.delegateChildReset();
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
// 如果 insertBefore 的位置在 childNodes 的 2/3 之后,则采用第二种方式,避免 childNodes 的全量更新
|
|
282
|
+
this.updateSingleChild(index);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
/** Delegates a removal after logical detachment and event identity cleanup. */
|
|
288
|
+
delegateChildRemoval(_child, options) {
|
|
289
|
+
if (this._root && options.doUpdate !== false) {
|
|
290
|
+
this.delegateChildReset();
|
|
291
|
+
}
|
|
292
|
+
}
|
|
282
293
|
remove(options) {
|
|
283
294
|
var _a;
|
|
284
295
|
(_a = this.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(this, options);
|
|
@@ -287,15 +298,6 @@ class TaroNode extends TaroEventTarget {
|
|
|
287
298
|
return this.childNodes.length > 0;
|
|
288
299
|
}
|
|
289
300
|
enqueueUpdate(payload) {
|
|
290
|
-
/*
|
|
291
|
-
* The outlet is the structural boundary between singleton App hosts and Page roots in Taro's in-memory tree. Its
|
|
292
|
-
* children must remain attached there for React ancestry, event ownership, unmounting, and Taro parent links, while
|
|
293
|
-
* each Page root independently schedules its own page.* native updates. Allowing outlet child mutations to bubble
|
|
294
|
-
* into the App scheduler would fan Page topology out as app.* data and duplicate work across every mounted Page.
|
|
295
|
-
* Suppress only this native update propagation; do not change the in-memory childNodes relationship.
|
|
296
|
-
*/
|
|
297
|
-
if (this.nodeName === 'vpt_page_outlet')
|
|
298
|
-
return;
|
|
299
301
|
var _a;
|
|
300
302
|
(_a = this._root) === null || _a === void 0 ? void 0 : _a.enqueueUpdate(payload);
|
|
301
303
|
}
|
package/dist/runtime/dom/root.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { hooks, isFunction, isArray, isUndefined } from '@tarojs/shared';
|
|
2
|
-
import { ROOT_STR, SET_DATA, PAGE_INIT, CUSTOM_WRAPPER
|
|
2
|
+
import { ROOT_STR, SET_DATA, PAGE_INIT, CUSTOM_WRAPPER } from '../constants/index.js';
|
|
3
3
|
import { options } from '../options.js';
|
|
4
4
|
import { perf } from '../perf.js';
|
|
5
5
|
import { isComment, customWrapperCache } from '../utils/index.js';
|
|
@@ -50,14 +50,7 @@ class TaroRootElement extends TaroElement {
|
|
|
50
50
|
this.tagName = ROOT_STR.toUpperCase();
|
|
51
51
|
}
|
|
52
52
|
get _path() {
|
|
53
|
-
|
|
54
|
-
* Both the singleton App host and every Page host are now real TaroRootElement schedulers. Their structural parent
|
|
55
|
-
* distinguishes ownership without a mode flag: the App root is the sole root directly below the document's
|
|
56
|
-
* <container>, while Page roots live below vpt_page_outlet. Every descendant derives its setData path from this one
|
|
57
|
-
* prefix, yielding direct app.* and page.* payloads without host overrides or per-update path translation. nodeName
|
|
58
|
-
* remains root in both cases, preserving Taro's host, event, and scheduler semantics.
|
|
59
|
-
*/
|
|
60
|
-
return this.parentNode && this.parentNode.nodeName === CONTAINER ? 'app' : 'page';
|
|
53
|
+
return ROOT_STR;
|
|
61
54
|
}
|
|
62
55
|
get _root() {
|
|
63
56
|
return this;
|
|
@@ -83,13 +76,14 @@ class TaroRootElement extends TaroElement {
|
|
|
83
76
|
perf.start(setDataMark);
|
|
84
77
|
const data = Object.create(null);
|
|
85
78
|
/*
|
|
86
|
-
* During the first render Taro replaces the leading child
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
79
|
+
* During the first render Taro replaces the leading child and removes redundant descendant writes from that
|
|
80
|
+
* same batch. Reset paths must use the root's actual _path, just like ordinary descendant payloads: VPT's App
|
|
81
|
+
* and Page schedulers use app.* and page.*, while the default root uses root.*. Recognize both indexed-path
|
|
82
|
+
* spellings so descendant writes are discarded before their lazy values are evaluated. Initial and
|
|
83
|
+
* steady-state scheduling therefore share one namespace for every root.
|
|
90
84
|
*/
|
|
91
85
|
const resetPaths = new Set(initRender
|
|
92
|
-
? [
|
|
86
|
+
? [`${this._path}.cn.[0]`, `${this._path}.cn[0]`]
|
|
93
87
|
: []);
|
|
94
88
|
while (this.updatePayloads.length > 0) {
|
|
95
89
|
const { path, value } = this.updatePayloads.shift();
|
|
@@ -9,6 +9,8 @@ declare class Style {
|
|
|
9
9
|
private setCssVariables;
|
|
10
10
|
get cssText(): string;
|
|
11
11
|
set cssText(str: string);
|
|
12
|
+
/** Delegates after logical style changes and cssText batching, before the default template payload is prepared. */
|
|
13
|
+
delegateStyleUpdate(): void;
|
|
12
14
|
setProperty(propertyName: string, value?: string | null): void;
|
|
13
15
|
removeProperty(propertyName: string): string;
|
|
14
16
|
getPropertyValue(propertyName: string): any;
|
|
@@ -11,15 +11,6 @@ function recordCss(obj) {
|
|
|
11
11
|
oldValue: obj.cssText
|
|
12
12
|
});
|
|
13
13
|
}
|
|
14
|
-
function enqueueUpdate(obj) {
|
|
15
|
-
const element = obj._element;
|
|
16
|
-
if (element._root) {
|
|
17
|
-
element.enqueueUpdate({
|
|
18
|
-
path: `${element._path}.${"st" /* Shortcuts.Style */}`,
|
|
19
|
-
value: obj.cssText
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
14
|
function setStyle(newVal, styleKey) {
|
|
24
15
|
process.env.NODE_ENV !== 'production' && warn(isString(newVal) && newVal.length > PROPERTY_THRESHOLD, `Style 属性 ${styleKey} 的值数据量过大,可能会影响渲染性能,考虑使用 CSS 类或其它方案替代。`);
|
|
25
16
|
const old = this[styleKey];
|
|
@@ -34,7 +25,7 @@ function setStyle(newVal, styleKey) {
|
|
|
34
25
|
this._usedStyleProp.add(styleKey);
|
|
35
26
|
this._value[styleKey] = newVal;
|
|
36
27
|
}
|
|
37
|
-
!this._pending &&
|
|
28
|
+
!this._pending && this.delegateStyleUpdate();
|
|
38
29
|
}
|
|
39
30
|
function initStyle(ctor, styleProperties) {
|
|
40
31
|
const properties = {};
|
|
@@ -99,7 +90,7 @@ class Style {
|
|
|
99
90
|
});
|
|
100
91
|
if (str === '' || isUndefined(str) || isNull(str)) {
|
|
101
92
|
this._pending = false;
|
|
102
|
-
|
|
93
|
+
this.delegateStyleUpdate();
|
|
103
94
|
return;
|
|
104
95
|
}
|
|
105
96
|
const rules = str.split(';');
|
|
@@ -117,7 +108,17 @@ class Style {
|
|
|
117
108
|
this.setProperty(propName.trim(), val.trim());
|
|
118
109
|
}
|
|
119
110
|
this._pending = false;
|
|
120
|
-
|
|
111
|
+
this.delegateStyleUpdate();
|
|
112
|
+
}
|
|
113
|
+
/** Delegates the completed style mutation; cssText assignments finish their synchronous batch before calling it. */
|
|
114
|
+
delegateStyleUpdate() {
|
|
115
|
+
const element = this._element;
|
|
116
|
+
if (element._root) {
|
|
117
|
+
element.enqueueUpdate({
|
|
118
|
+
path: `${element._path}.${"st" /* Shortcuts.Style */}`,
|
|
119
|
+
value: this.cssText
|
|
120
|
+
});
|
|
121
|
+
}
|
|
121
122
|
}
|
|
122
123
|
setProperty(propertyName, value) {
|
|
123
124
|
if (propertyName[0] === '-') {
|
|
@@ -12,6 +12,11 @@ declare class TaroText extends TaroNode {
|
|
|
12
12
|
get nodeValue(): string;
|
|
13
13
|
set data(text: string);
|
|
14
14
|
get data(): string;
|
|
15
|
+
/**
|
|
16
|
+
* Delegates a text update after Taro records the mutation and stores the logical value.
|
|
17
|
+
* The default prepares the template payload; textContent, nodeValue and data share this boundary.
|
|
18
|
+
*/
|
|
19
|
+
delegateTextUpdate(text: string): void;
|
|
15
20
|
}
|
|
16
21
|
|
|
17
22
|
export { TaroText };
|
package/dist/runtime/dom/text.js
CHANGED
|
@@ -15,10 +15,7 @@ class TaroText extends TaroNode {
|
|
|
15
15
|
oldValue: this._value
|
|
16
16
|
});
|
|
17
17
|
this._value = text;
|
|
18
|
-
this.
|
|
19
|
-
path: `${this._path}.${"v" /* Shortcuts.Text */}`,
|
|
20
|
-
value: text
|
|
21
|
-
});
|
|
18
|
+
this.delegateTextUpdate(text);
|
|
22
19
|
}
|
|
23
20
|
get textContent() {
|
|
24
21
|
return this._value;
|
|
@@ -35,6 +32,13 @@ class TaroText extends TaroNode {
|
|
|
35
32
|
get data() {
|
|
36
33
|
return this._value;
|
|
37
34
|
}
|
|
35
|
+
/** Delegates the logical value after its mutation record; hosts can replace template payload preparation. */
|
|
36
|
+
delegateTextUpdate(text) {
|
|
37
|
+
this.enqueueUpdate({
|
|
38
|
+
path: `${this._path}.${"v" /* Shortcuts.Text */}`,
|
|
39
|
+
value: text
|
|
40
|
+
});
|
|
41
|
+
}
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
export { TaroText };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-plugin-taro-runtime",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.13",
|
|
4
4
|
"description": "Taro runtime, React, and platform support for vite-plugin-taro.",
|
|
5
5
|
"author": "sep2",
|
|
6
6
|
"license": "MIT",
|
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
"import": "./dist/runtime/index.js",
|
|
12
12
|
"default": "./dist/runtime/index.js"
|
|
13
13
|
},
|
|
14
|
+
"./runtime/tt-document": {
|
|
15
|
+
"types": "./types/tt-document.d.ts",
|
|
16
|
+
"import": "./dist/runtime/bom/document.js",
|
|
17
|
+
"default": "./dist/runtime/bom/document.js"
|
|
18
|
+
},
|
|
14
19
|
"./runtime/h5": {
|
|
15
20
|
"types": "./dist/runtime/runtime.esm.d.ts",
|
|
16
21
|
"import": "./dist/runtime/runtime.esm.js",
|
|
@@ -109,6 +114,7 @@
|
|
|
109
114
|
},
|
|
110
115
|
"files": [
|
|
111
116
|
"dist",
|
|
117
|
+
"types",
|
|
112
118
|
"LICENSE",
|
|
113
119
|
"README.md"
|
|
114
120
|
],
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { MpEvent } from 'vite-plugin-taro-runtime/runtime/mini'
|
|
2
|
+
|
|
3
|
+
/** TT SDK nodes are Page-local presentation instances; React refs retain TaroNode identities. */
|
|
4
|
+
export interface TTNativeNode {
|
|
5
|
+
readonly nodeType: number
|
|
6
|
+
readonly childNodes: readonly TTNativeNode[]
|
|
7
|
+
readonly firstChild: TTNativeNode | null
|
|
8
|
+
readonly nextSibling: TTNativeNode | null
|
|
9
|
+
readonly parentNode: TTNativeNode | null
|
|
10
|
+
nodeValue: string
|
|
11
|
+
appendChild(child: TTNativeNode): void
|
|
12
|
+
insertBefore(child: TTNativeNode, before: TTNativeNode | null): void
|
|
13
|
+
removeChild(child: TTNativeNode): void
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface TTNativeElement extends TTNativeNode {
|
|
17
|
+
id: string
|
|
18
|
+
readonly attributes: Readonly<Record<string, unknown>>
|
|
19
|
+
setAttribute(name: string, value: unknown): void
|
|
20
|
+
removeAttribute(name: string): void
|
|
21
|
+
addEventListener(name: string, listener: (event: MpEvent) => unknown): void
|
|
22
|
+
removeEventListener(name: string, listener: (event: MpEvent) => unknown): void
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface TTNativeComponent extends TTNativeElement {
|
|
26
|
+
readonly componentName: string
|
|
27
|
+
/** SDK native components accept their default-slot value as one node or an array of nodes. */
|
|
28
|
+
appendChild(children: TTNativeNode | readonly TTNativeNode[]): void
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface TTNativeDocument {
|
|
32
|
+
getPageDocumentById(id: number): TTNativeElement | undefined
|
|
33
|
+
createElement(name: string): TTNativeElement
|
|
34
|
+
createTextNode(text: string): TTNativeNode
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Adapts the current TT appDocument through Taro's existing native document factory. */
|
|
38
|
+
export declare function createTTDomDocument(): TTNativeDocument
|