transone 0.1.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 +17 -0
- package/dist/core/app.d.ts +114 -0
- package/dist/core/component/base.d.ts +79 -0
- package/dist/core/component/index.d.ts +4 -0
- package/dist/core/component.d.ts +1 -0
- package/dist/core/document.d.ts +32 -0
- package/dist/core/form.d.ts +24 -0
- package/dist/core/index.d.ts +9 -0
- package/dist/core/model.d.ts +18 -0
- package/dist/core/reactive/scheduler.d.ts +32 -0
- package/dist/core/reactive/types.d.ts +24 -0
- package/dist/core/reactive.d.ts +77 -0
- package/dist/core/renderer/element-strategy.d.ts +32 -0
- package/dist/core/renderer/props.d.ts +9 -0
- package/dist/core/renderer/types.d.ts +37 -0
- package/dist/core/renderer.d.ts +43 -0
- package/dist/core/template.d.ts +50 -0
- package/dist/core/vnode.d.ts +104 -0
- package/dist/dom/index.d.ts +612 -0
- package/dist/dom/index.js +4 -0
- package/dist/dom/index.js.map +10 -0
- package/dist/index-3t506ckz.js +12 -0
- package/dist/index-3t506ckz.js.map +25 -0
- package/dist/index-mbmajrpr.js +26 -0
- package/dist/index-mbmajrpr.js.map +11 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +11 -0
- package/dist/router/history.d.ts +5 -0
- package/dist/router/index.d.ts +112 -0
- package/dist/router/index.js +4 -0
- package/dist/router/index.js.map +9 -0
- package/dist/router/instance.d.ts +26 -0
- package/dist/router/matcher.d.ts +7 -0
- package/dist/style/StyleManager.d.ts +18 -0
- package/dist/style/class-style.d.ts +0 -0
- package/dist/style/id-style.d.ts +0 -0
- package/dist/style/index.d.ts +2 -0
- package/dist/style/index.js +4 -0
- package/dist/style/index.js.map +9 -0
- package/dist/style/sheet.d.ts +13 -0
- package/dist/style/style.d.ts +0 -0
- package/package.json +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# @geektech/transone
|
|
2
|
+
|
|
3
|
+
TransOne 核心框架包:一份 TypeScript 源码,跨端框架的核心运行时模型。
|
|
4
|
+
|
|
5
|
+
- 响应式系统:`reactive`、`readonly`、`effect`、`stop`、`computed`、`ref`、`watch`
|
|
6
|
+
- 面向对象组件:`Component<Props, State>`、生命周期、事件、插槽
|
|
7
|
+
- 策略化渲染:`RenderStrategy` 按 VNode 类型分发(文本 / 元素 / 组件 / 插槽)
|
|
8
|
+
- 内置路由:`createRouter`、`RouterView`、`RouterLink`
|
|
9
|
+
- 样式管理:`StyleManager`
|
|
10
|
+
|
|
11
|
+
与 TSone 同源:核心公开 API 复用 TSone,Web 产物可直接复用 TSone 渲染策略。
|
|
12
|
+
编译器见 [@geektech/transone-cli](../transone-cli)。
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
bun test # 测试
|
|
16
|
+
bun run build # 构建 dist(ESM + .d.ts)
|
|
17
|
+
```
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { ComponentConstructor, ComponentProps, InjectionKey, InjectionResult } from './component';
|
|
2
|
+
import { type HtmlDocumentBody, type HtmlDocumentOptions } from './document';
|
|
3
|
+
import type { Router } from '../router';
|
|
4
|
+
export interface Plugin {
|
|
5
|
+
install: (app: OneApp, ...args: unknown[]) => void;
|
|
6
|
+
onMounted?: (app: OneApp) => void;
|
|
7
|
+
onUpdated?: (app: OneApp) => void;
|
|
8
|
+
onBeforeUnmount?: (app: OneApp) => void;
|
|
9
|
+
}
|
|
10
|
+
export type AppDocumentOptions = Partial<Omit<HtmlDocumentOptions, 'body'>> & {
|
|
11
|
+
body?: HtmlDocumentBody;
|
|
12
|
+
};
|
|
13
|
+
export type AppDocumentRenderOptions = AppDocumentOptions;
|
|
14
|
+
export interface AppOptions<TState = Record<string, unknown>, TConfig = Record<string, unknown>, TRootProps extends ComponentProps = ComponentProps> {
|
|
15
|
+
/** 根组件构造函数 */
|
|
16
|
+
root?: ComponentConstructor<TRootProps>;
|
|
17
|
+
/** 根组件 props */
|
|
18
|
+
rootProps?: TRootProps;
|
|
19
|
+
/** 应用挂载点,默认 #app */
|
|
20
|
+
rootElement?: string | Element;
|
|
21
|
+
/** 全局状态 */
|
|
22
|
+
state?: TState;
|
|
23
|
+
/** 全局配置 */
|
|
24
|
+
config?: TConfig;
|
|
25
|
+
/** HTML 文档壳配置,用于 dev/build 生成入口页面 */
|
|
26
|
+
document?: AppDocumentOptions;
|
|
27
|
+
}
|
|
28
|
+
export interface AppContext<TConfig = Record<string, unknown>> {
|
|
29
|
+
app: OneApp;
|
|
30
|
+
version: string;
|
|
31
|
+
config: TConfig;
|
|
32
|
+
router?: Router;
|
|
33
|
+
}
|
|
34
|
+
export declare class OneApp<TState extends object = Record<string, unknown>, TConfig extends object = Record<string, unknown>, TRootProps extends ComponentProps = ComponentProps> {
|
|
35
|
+
private options;
|
|
36
|
+
private container;
|
|
37
|
+
private rootInstance;
|
|
38
|
+
private mounted;
|
|
39
|
+
private templateEngine;
|
|
40
|
+
private readonly appContext;
|
|
41
|
+
private readonly providers;
|
|
42
|
+
private plugins;
|
|
43
|
+
private unmountedCallback?;
|
|
44
|
+
router?: Router;
|
|
45
|
+
constructor(options?: AppOptions<TState, TConfig, TRootProps>);
|
|
46
|
+
private handleError;
|
|
47
|
+
/**
|
|
48
|
+
* 渲染错误UI
|
|
49
|
+
*/
|
|
50
|
+
private renderErrorUI;
|
|
51
|
+
/**
|
|
52
|
+
* 使用插件
|
|
53
|
+
*/
|
|
54
|
+
use(plugin: Plugin, ...args: unknown[]): this;
|
|
55
|
+
/**
|
|
56
|
+
* 挂载应用
|
|
57
|
+
*/
|
|
58
|
+
mount(): void;
|
|
59
|
+
/**
|
|
60
|
+
* 卸载应用
|
|
61
|
+
*/
|
|
62
|
+
unmount(): void;
|
|
63
|
+
/**
|
|
64
|
+
* 应用是否正在运行
|
|
65
|
+
*/
|
|
66
|
+
isRunning(): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* 更新根组件
|
|
69
|
+
*/
|
|
70
|
+
updateRootComponent(component: ComponentConstructor<TRootProps>): void;
|
|
71
|
+
/**
|
|
72
|
+
* 更新应用状态
|
|
73
|
+
*/
|
|
74
|
+
update(state?: Partial<TState>): this;
|
|
75
|
+
/**
|
|
76
|
+
* 获取应用上下文
|
|
77
|
+
*/
|
|
78
|
+
getContext(): AppContext<TConfig>;
|
|
79
|
+
provide<T>(key: InjectionKey<T>, value: T): this;
|
|
80
|
+
inject<T>(key: InjectionKey<T>): T | undefined;
|
|
81
|
+
inject<T>(key: InjectionKey<T>, fallback: T): T;
|
|
82
|
+
resolveInjection<T>(key: InjectionKey<T>): InjectionResult<T>;
|
|
83
|
+
/**
|
|
84
|
+
* 获取应用状态
|
|
85
|
+
*/
|
|
86
|
+
getState(): TState | undefined;
|
|
87
|
+
/**
|
|
88
|
+
* 设置应用状态
|
|
89
|
+
*/
|
|
90
|
+
setState(newState: TState): this;
|
|
91
|
+
/**
|
|
92
|
+
* 监听应用卸载
|
|
93
|
+
*/
|
|
94
|
+
onUnmounted(callback: () => void): this;
|
|
95
|
+
/**
|
|
96
|
+
* 生成应用入口 HTML 文档
|
|
97
|
+
*/
|
|
98
|
+
renderHtmlDocument(options?: AppDocumentRenderOptions): string;
|
|
99
|
+
/**
|
|
100
|
+
* 解析根元素
|
|
101
|
+
*/
|
|
102
|
+
private resolveRootElement;
|
|
103
|
+
private resolveMountContainer;
|
|
104
|
+
private createMountDocumentBody;
|
|
105
|
+
private createMountElementFromSelector;
|
|
106
|
+
private mergeDocumentScripts;
|
|
107
|
+
private onMounted;
|
|
108
|
+
private onUpdated;
|
|
109
|
+
private onBeforeUnmount;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* 创建应用实例
|
|
113
|
+
*/
|
|
114
|
+
export declare function createApp<TState extends object = Record<string, unknown>, TConfig extends object = Record<string, unknown>, TRootProps extends ComponentProps = ComponentProps>(options?: AppOptions<TState, TConfig, TRootProps>): OneApp<TState, TConfig, TRootProps>;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { StyleManager } from '../../style/StyleManager';
|
|
2
|
+
import { ComponentInstance } from '../renderer';
|
|
3
|
+
import type { VNode } from '../vnode';
|
|
4
|
+
export type ComponentProps = object;
|
|
5
|
+
export type ComponentState = object;
|
|
6
|
+
export type ComponentEventListener = (...args: unknown[]) => void;
|
|
7
|
+
export type InjectionKey<T> = (string | symbol) & {
|
|
8
|
+
readonly __injectionType?: T;
|
|
9
|
+
};
|
|
10
|
+
export interface InjectionResult<T> {
|
|
11
|
+
found: boolean;
|
|
12
|
+
value: T | undefined;
|
|
13
|
+
}
|
|
14
|
+
export type ComponentConstructor<TProps extends ComponentProps = ComponentProps, TState extends ComponentState = ComponentState> = new (props?: TProps) => Component<TProps, TState>;
|
|
15
|
+
export type AnyComponentConstructor = new (props?: never) => Component<ComponentProps, ComponentState>;
|
|
16
|
+
export declare abstract class Component<TProps extends ComponentProps = ComponentProps, TState extends ComponentState = ComponentState> implements ComponentInstance {
|
|
17
|
+
protected props: TProps;
|
|
18
|
+
private vnode;
|
|
19
|
+
private el;
|
|
20
|
+
private readonly renderer;
|
|
21
|
+
private readonly templateEngine;
|
|
22
|
+
private readonly childComponents;
|
|
23
|
+
private readonly eventListeners;
|
|
24
|
+
private readonly providers;
|
|
25
|
+
private readonly updateEffect;
|
|
26
|
+
private appContext;
|
|
27
|
+
private parentComponent;
|
|
28
|
+
private elementChangeListener;
|
|
29
|
+
protected styleManager: StyleManager;
|
|
30
|
+
state: TState;
|
|
31
|
+
mounted: boolean;
|
|
32
|
+
constructor(props?: TProps);
|
|
33
|
+
protected abstract initState(): TState;
|
|
34
|
+
protected abstract initStyles(): void;
|
|
35
|
+
protected abstract render(): VNode;
|
|
36
|
+
mount(container: HTMLElement): void;
|
|
37
|
+
mountToNode(): Node;
|
|
38
|
+
update(): void;
|
|
39
|
+
unmount(): void;
|
|
40
|
+
setProps(props: Partial<TProps>): void;
|
|
41
|
+
setState(state: Partial<TState>): void;
|
|
42
|
+
setAppContext(context: unknown): void;
|
|
43
|
+
setParentComponent(parent: ComponentInstance | null): void;
|
|
44
|
+
getParentComponent(): ComponentInstance | null;
|
|
45
|
+
setElementChangeListener(listener: (previousElement: Node, nextElement: Node) => void): void;
|
|
46
|
+
provide<T>(key: InjectionKey<T>, value: T): void;
|
|
47
|
+
inject<T>(key: InjectionKey<T>): T | undefined;
|
|
48
|
+
inject<T>(key: InjectionKey<T>, fallback: T): T;
|
|
49
|
+
resolveInjection<T>(key: InjectionKey<T>): InjectionResult<T>;
|
|
50
|
+
getElement(): Node | null;
|
|
51
|
+
protected beforeMount(): void;
|
|
52
|
+
protected onMounted(): void;
|
|
53
|
+
protected beforeUpdate(): void;
|
|
54
|
+
protected onUpdated(): void;
|
|
55
|
+
protected beforeUnmount(): void;
|
|
56
|
+
protected onUnmounted(): void;
|
|
57
|
+
/**
|
|
58
|
+
* 错误边界钩子:后代组件渲染或更新抛错时被调用。
|
|
59
|
+
* 返回 false 表示错误已被处理并停止继续向上传播;
|
|
60
|
+
* 返回 true 或 undefined 时错误继续冒泡到更外层边界。
|
|
61
|
+
*/
|
|
62
|
+
protected onErrorCaptured?(error: unknown, instance: ComponentInstance): boolean | void;
|
|
63
|
+
/**
|
|
64
|
+
* 沿组件父链寻找最近的错误边界。返回 true 表示错误已被边界处理。
|
|
65
|
+
*/
|
|
66
|
+
private dispatchError;
|
|
67
|
+
protected getContext(): unknown;
|
|
68
|
+
protected get router(): unknown;
|
|
69
|
+
protected emit(eventName: string, ...args: unknown[]): void;
|
|
70
|
+
on(eventName: string, listener: ComponentEventListener): () => void;
|
|
71
|
+
off(eventName: string, listener: ComponentEventListener): void;
|
|
72
|
+
private createRenderContext;
|
|
73
|
+
private collectSlots;
|
|
74
|
+
private getSlotName;
|
|
75
|
+
private normalizeSlotChild;
|
|
76
|
+
private getRouterFrom;
|
|
77
|
+
private getRouterFromGlobalApp;
|
|
78
|
+
private resolveAppInjection;
|
|
79
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Component } from './base';
|
|
2
|
+
import type { AnyComponentConstructor, ComponentConstructor, ComponentEventListener, InjectionKey, InjectionResult, ComponentProps, ComponentState } from './base';
|
|
3
|
+
export { Component };
|
|
4
|
+
export type { AnyComponentConstructor, ComponentConstructor, ComponentEventListener, InjectionKey, InjectionResult, ComponentProps, ComponentState, };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './component/index';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Renderable } from './renderer/types';
|
|
2
|
+
import { type StyleSheet } from '../style/sheet';
|
|
3
|
+
export { renderStyleSheet, type StyleAtRule, type StyleProperties, type StyleRule, type StyleSheet, type StyleSheetEntry, type StyleValue, } from '../style/sheet';
|
|
4
|
+
export type HtmlAttributeValue = string | number | boolean | null | undefined;
|
|
5
|
+
export type HtmlAttributes = Record<string, HtmlAttributeValue>;
|
|
6
|
+
export type HtmlDocumentBody = Renderable | Renderable[];
|
|
7
|
+
export interface HtmlHeadElement {
|
|
8
|
+
tag: string;
|
|
9
|
+
attributes?: HtmlAttributes;
|
|
10
|
+
text?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface HtmlScript {
|
|
13
|
+
src: string;
|
|
14
|
+
type?: string;
|
|
15
|
+
async?: boolean;
|
|
16
|
+
defer?: boolean;
|
|
17
|
+
attributes?: HtmlAttributes;
|
|
18
|
+
}
|
|
19
|
+
export interface HtmlDocumentOptions {
|
|
20
|
+
title: string;
|
|
21
|
+
body: HtmlDocumentBody;
|
|
22
|
+
lang?: string;
|
|
23
|
+
charset?: string;
|
|
24
|
+
viewport?: string;
|
|
25
|
+
description?: string;
|
|
26
|
+
htmlAttributes?: HtmlAttributes;
|
|
27
|
+
bodyAttributes?: HtmlAttributes;
|
|
28
|
+
head?: HtmlHeadElement[];
|
|
29
|
+
styles?: StyleSheet;
|
|
30
|
+
scripts?: HtmlScript[];
|
|
31
|
+
}
|
|
32
|
+
export declare function renderHtmlDocument(options: HtmlDocumentOptions): string;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type ValidationResult = boolean | string;
|
|
2
|
+
export type ValidationRule<T = unknown> = (value: T, model: object) => ValidationResult;
|
|
3
|
+
export type ValidationRules<TModel extends object> = {
|
|
4
|
+
[TPath in keyof TModel & string]?: readonly ValidationRule[];
|
|
5
|
+
} & Record<string, readonly ValidationRule[] | undefined>;
|
|
6
|
+
export interface FieldValidationResult {
|
|
7
|
+
valid: boolean;
|
|
8
|
+
errors: string[];
|
|
9
|
+
}
|
|
10
|
+
export interface FormValidationResult {
|
|
11
|
+
valid: boolean;
|
|
12
|
+
errors: Record<string, string[]>;
|
|
13
|
+
}
|
|
14
|
+
export interface FormController<TModel extends object> {
|
|
15
|
+
readonly model: TModel;
|
|
16
|
+
readonly errors: Record<string, string[]>;
|
|
17
|
+
validate(): FormValidationResult;
|
|
18
|
+
validateField(path: string): FieldValidationResult;
|
|
19
|
+
resetErrors(): void;
|
|
20
|
+
}
|
|
21
|
+
export declare function required(message?: string): ValidationRule;
|
|
22
|
+
export declare function minLength(length: number, message?: string): ValidationRule;
|
|
23
|
+
export declare function validate(rule: ValidationRule): ValidationRule;
|
|
24
|
+
export declare function createForm<TModel extends object>(model: TModel, rules: ValidationRules<TModel>): FormController<TModel>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface ModelBindingOptions {
|
|
2
|
+
path: string;
|
|
3
|
+
parse?: (value: unknown) => unknown;
|
|
4
|
+
format?: (value: unknown) => string;
|
|
5
|
+
}
|
|
6
|
+
export type ModelBinding = string | ModelBindingOptions;
|
|
7
|
+
type ModelState = Record<string, unknown>;
|
|
8
|
+
export declare function modelPath(binding: ModelBinding): string;
|
|
9
|
+
export declare function getModelValue(state: ModelState, path: string): unknown;
|
|
10
|
+
export declare function setModelValue(state: ModelState, path: string, value: unknown): void;
|
|
11
|
+
export declare class ModelBindingController {
|
|
12
|
+
private readonly bindings;
|
|
13
|
+
bind(element: HTMLElement, binding: ModelBinding, state: ModelState): void;
|
|
14
|
+
cleanup(element: HTMLElement): void;
|
|
15
|
+
private isSupportedControl;
|
|
16
|
+
private sameBinding;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ReactiveEffect } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* 响应式 effect 批处理调度器。
|
|
4
|
+
*
|
|
5
|
+
* 同一批同步状态变更(同一个任务内的多次 mutation)只会触发一次 effect
|
|
6
|
+
* 运行:effect 被 enqueue 后去重入队,并在微任务中统一冲刷(flush)。
|
|
7
|
+
* 冲刷期间的重复入队会在同一轮循环中继续处理,直到队列清空。
|
|
8
|
+
*
|
|
9
|
+
* 组件渲染通过该调度器合并更新:连续修改 state 不会逐次重渲染,
|
|
10
|
+
* 与 Vue 微任务调度 / React 自动批处理的语义一致。
|
|
11
|
+
*/
|
|
12
|
+
export declare class ReactiveScheduler {
|
|
13
|
+
private readonly pending;
|
|
14
|
+
private flushing;
|
|
15
|
+
private flushPromise;
|
|
16
|
+
private flushResolve;
|
|
17
|
+
/**
|
|
18
|
+
* 将 effect 加入待冲刷队列(去重)。
|
|
19
|
+
*/
|
|
20
|
+
enqueue(effect: ReactiveEffect): void;
|
|
21
|
+
/**
|
|
22
|
+
* 同步冲刷队列:立即执行所有待运行的 effect。
|
|
23
|
+
* 若当前正处于一次冲刷中(例如在 effect 内部调用),则直接返回,
|
|
24
|
+
* 由正在进行的冲刷循环负责处理新增任务。
|
|
25
|
+
*/
|
|
26
|
+
flush(): void;
|
|
27
|
+
/**
|
|
28
|
+
* 返回一个在待冲刷的 effect 全部执行完成后 resolve 的 Promise。
|
|
29
|
+
* 若当前没有待冲刷任务,立即 resolve。
|
|
30
|
+
*/
|
|
31
|
+
nextTick(): Promise<void>;
|
|
32
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface ReactiveEffect<T = unknown> {
|
|
2
|
+
(): T | undefined;
|
|
3
|
+
deps: Set<ReactiveEffect>[];
|
|
4
|
+
id: number;
|
|
5
|
+
active: boolean;
|
|
6
|
+
scheduler?: (effect: ReactiveEffect) => void;
|
|
7
|
+
}
|
|
8
|
+
export interface ReactiveEffectOptions {
|
|
9
|
+
lazy?: boolean;
|
|
10
|
+
scheduler?: (effect: ReactiveEffect) => void;
|
|
11
|
+
throwOnError?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface ComputedRef<T> {
|
|
14
|
+
readonly value: T;
|
|
15
|
+
}
|
|
16
|
+
export declare const IS_REACTIVE: unique symbol;
|
|
17
|
+
export declare const IS_READONLY: unique symbol;
|
|
18
|
+
export declare const IS_REF: unique symbol;
|
|
19
|
+
export interface Ref<T = unknown> {
|
|
20
|
+
value: T;
|
|
21
|
+
}
|
|
22
|
+
export declare const MUTATING_ARRAY_METHODS: readonly ["push", "pop", "shift", "unshift", "splice", "sort", "reverse"];
|
|
23
|
+
export declare function hasReactiveFlag(value: object, flag: typeof IS_REACTIVE | typeof IS_READONLY): boolean;
|
|
24
|
+
export declare function isObject(value: unknown): value is object;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { ComputedRef, Ref, ReactiveEffect, ReactiveEffectOptions } from './reactive/types';
|
|
2
|
+
import { ReactiveScheduler } from './reactive/scheduler';
|
|
3
|
+
export type { ComputedRef, Ref, ReactiveEffect, ReactiveEffectOptions, } from './reactive/types';
|
|
4
|
+
export declare const reactiveScheduler: ReactiveScheduler;
|
|
5
|
+
/**
|
|
6
|
+
* 等待当前批次的响应式 effect 全部执行完成(通常是组件重渲染)。
|
|
7
|
+
* 修改 state 后需要立即读取 DOM 时使用:await nextTick()。
|
|
8
|
+
*/
|
|
9
|
+
export declare function nextTick(): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* 同步冲刷待执行的响应式 effect,立即完成组件重渲染。
|
|
12
|
+
* 一般仅测试或需要同步读 DOM 的场景使用。
|
|
13
|
+
*/
|
|
14
|
+
export declare function flushSync(): void;
|
|
15
|
+
export declare class ReactiveSystem {
|
|
16
|
+
private static instance;
|
|
17
|
+
private activeEffect;
|
|
18
|
+
private readonly effectStack;
|
|
19
|
+
private targetMap;
|
|
20
|
+
private reactiveMap;
|
|
21
|
+
private readonlyMap;
|
|
22
|
+
/** 反向映射:响应式代理 -> 原始对象,供 toRawValue 反查 */
|
|
23
|
+
private proxyMap;
|
|
24
|
+
private constructor();
|
|
25
|
+
static getInstance(): ReactiveSystem;
|
|
26
|
+
reactive<T extends object>(target: T): T;
|
|
27
|
+
/**
|
|
28
|
+
* 将响应式代理反查为原始对象;非代理值原样返回。
|
|
29
|
+
* 用于数组 includes/indexOf/lastIndexOf 的对比,让用户传入
|
|
30
|
+
* 原始对象也能命中数组中的响应式元素。
|
|
31
|
+
*/
|
|
32
|
+
private toRawValue;
|
|
33
|
+
/**
|
|
34
|
+
* 创建响应式数组
|
|
35
|
+
*/
|
|
36
|
+
private createReactiveArray;
|
|
37
|
+
readonly<T extends object>(target: T): Readonly<T>;
|
|
38
|
+
effect<T = unknown>(fn: () => T, options?: ReactiveEffectOptions): ReactiveEffect<T>;
|
|
39
|
+
/**
|
|
40
|
+
* 在指定 effect 的上下文中运行 fn,使 fn 内的响应式访问被收集到该 effect,
|
|
41
|
+
* 而不是当前外层 effect。组件渲染用它隔离依赖:子组件在父组件渲染期间
|
|
42
|
+
* 执行自身 render 时,子 state 的访问不会污染父组件的 effect。
|
|
43
|
+
*/
|
|
44
|
+
runWithEffect<T>(effect: ReactiveEffect, fn: () => T): T;
|
|
45
|
+
computed<T>(getter: () => T): ComputedRef<T>;
|
|
46
|
+
private cleanup;
|
|
47
|
+
private track;
|
|
48
|
+
private trigger;
|
|
49
|
+
stop(effect: ReactiveEffect): void;
|
|
50
|
+
}
|
|
51
|
+
export declare function reactive<T extends object>(target: T): T;
|
|
52
|
+
export declare function readonly<T extends object>(target: T): Readonly<T>;
|
|
53
|
+
export declare function effect<T = unknown>(fn: () => T, options?: ReactiveEffectOptions): ReactiveEffect<T>;
|
|
54
|
+
export declare function computed<T>(getter: () => T): ComputedRef<T>;
|
|
55
|
+
export declare function ref<T>(value: T): Ref<T>;
|
|
56
|
+
export declare function isRef(value: unknown): value is Ref<unknown>;
|
|
57
|
+
export declare function unref<T>(value: T | Ref<T>): T;
|
|
58
|
+
export declare function stop(effect: ReactiveEffect): void;
|
|
59
|
+
export interface WatchSource<T> {
|
|
60
|
+
value: T;
|
|
61
|
+
}
|
|
62
|
+
export type WatchCallback<T> = (value: T, oldValue: T | undefined, onCleanup: (cleanup: () => void) => void) => void;
|
|
63
|
+
export interface WatchOptions {
|
|
64
|
+
/** 建立后立即执行一次回调(此时 oldValue 为 undefined) */
|
|
65
|
+
immediate?: boolean;
|
|
66
|
+
/** 深度追踪 getter 返回值的嵌套属性变化 */
|
|
67
|
+
deep?: boolean;
|
|
68
|
+
/** 变化发生时同步回调(默认随调度器批处理,同一批变化只回调一次) */
|
|
69
|
+
sync?: boolean;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* 侦听响应式源(getter 或 ref)的变化并执行回调。
|
|
73
|
+
* 返回一个用于停止侦听的函数。
|
|
74
|
+
*/
|
|
75
|
+
export declare function watch<T>(source: WatchSource<T> | (() => T), callback: WatchCallback<T>, options?: WatchOptions): () => void;
|
|
76
|
+
export declare function isReactive(value: unknown): boolean;
|
|
77
|
+
export declare function isReadonly(value: unknown): boolean;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { HTMLNode } from '../vnode';
|
|
2
|
+
import type { RenderRuntimeContext, RenderStrategy, Renderable } from './types';
|
|
3
|
+
export declare const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
|
|
4
|
+
/**
|
|
5
|
+
* 仅包含 HTML 中不存在的 SVG 专属标签:这些标签必须通过
|
|
6
|
+
* createElementNS 创建,否则会落入 HTML 命名空间而无法渲染。
|
|
7
|
+
* 与 HTML 重名的标签(title/desc/a/image 等)不在此列,避免误伤。
|
|
8
|
+
*/
|
|
9
|
+
export declare const SVG_TAGS: ReadonlySet<string>;
|
|
10
|
+
export declare class ElementRenderStrategy<TNode extends HTMLNode = HTMLNode> implements RenderStrategy<TNode> {
|
|
11
|
+
private readonly listeners;
|
|
12
|
+
private readonly effects;
|
|
13
|
+
private readonly modelBindings;
|
|
14
|
+
matches(vnode: Renderable): vnode is TNode;
|
|
15
|
+
mount(vnode: TNode, context: RenderRuntimeContext): Node;
|
|
16
|
+
patch(oldVNode: TNode, newVNode: TNode, currentNode: Node, context: RenderRuntimeContext): Node;
|
|
17
|
+
unmount(vnode: TNode, currentNode: Node, context: RenderRuntimeContext): void;
|
|
18
|
+
protected mountChildren(element: Element, vnode: TNode, context: RenderRuntimeContext): void;
|
|
19
|
+
protected updateChildren(element: Element, oldVNode: TNode, newVNode: TNode, context: RenderRuntimeContext): void;
|
|
20
|
+
protected unmountChildren(element: Element, vnode: TNode, context: RenderRuntimeContext): void;
|
|
21
|
+
private applyProps;
|
|
22
|
+
private applyDirections;
|
|
23
|
+
private updateOrdinaryChildren;
|
|
24
|
+
private updateKeyedChildren;
|
|
25
|
+
private hasOnlyKeyedChildren;
|
|
26
|
+
private assertNoDuplicateKeys;
|
|
27
|
+
private getVNodeKey;
|
|
28
|
+
private collectListeners;
|
|
29
|
+
private updateListeners;
|
|
30
|
+
private setupReactiveAttribute;
|
|
31
|
+
private trackEffect;
|
|
32
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface ParsedEventName {
|
|
2
|
+
eventName: string;
|
|
3
|
+
modifiers: Set<string>;
|
|
4
|
+
}
|
|
5
|
+
export declare function isEventProp(key: string): boolean;
|
|
6
|
+
export declare function eventNameFromProp(key: string): string;
|
|
7
|
+
export declare function parseEventName(event: string): ParsedEventName;
|
|
8
|
+
export declare function wrapEventHandler(handler: (event: Event) => void, modifiers: Set<string>): EventListener;
|
|
9
|
+
export declare function setStyleValue(style: CSSStyleDeclaration, property: string, value: string | number): void;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { TemplateEngine } from '../template';
|
|
2
|
+
import type { ComponentEventListener, ComponentProps } from '../component';
|
|
3
|
+
import type { InjectionKey, InjectionResult } from '../component';
|
|
4
|
+
import type { VNode } from '../vnode';
|
|
5
|
+
export interface ComponentInstance {
|
|
6
|
+
mountToNode(): Node;
|
|
7
|
+
update(): void;
|
|
8
|
+
unmount(): void;
|
|
9
|
+
setProps(props: Partial<ComponentProps>): void;
|
|
10
|
+
setAppContext?(context: unknown): void;
|
|
11
|
+
setParentComponent?(parent: ComponentInstance | null): void;
|
|
12
|
+
getParentComponent?(): ComponentInstance | null;
|
|
13
|
+
setElementChangeListener?(listener: (previousElement: Node, nextElement: Node) => void): void;
|
|
14
|
+
resolveInjection?<T>(key: InjectionKey<T>): InjectionResult<T>;
|
|
15
|
+
getElement(): Node | null;
|
|
16
|
+
on(eventName: string, listener: ComponentEventListener): () => void;
|
|
17
|
+
}
|
|
18
|
+
export type Renderable = VNode | string;
|
|
19
|
+
export interface RendererHost {
|
|
20
|
+
mount(vnode: Renderable, context: RenderRuntimeContext): Node;
|
|
21
|
+
patch(oldVNode: Renderable, newVNode: Renderable, currentNode: Node, context: RenderRuntimeContext): Node;
|
|
22
|
+
unmount(vnode: Renderable, currentNode: Node, context: RenderRuntimeContext): void;
|
|
23
|
+
}
|
|
24
|
+
export interface RenderRuntimeContext {
|
|
25
|
+
templateEngine: TemplateEngine;
|
|
26
|
+
appContext?: unknown;
|
|
27
|
+
renderer: RendererHost;
|
|
28
|
+
slots: Record<string, Array<VNode | string>>;
|
|
29
|
+
registerChild(component: ComponentInstance): void;
|
|
30
|
+
unregisterChild(component: ComponentInstance): void;
|
|
31
|
+
}
|
|
32
|
+
export interface RenderStrategy<T extends Renderable = Renderable> {
|
|
33
|
+
matches(vnode: Renderable): vnode is T;
|
|
34
|
+
mount(vnode: T, context: RenderRuntimeContext): Node;
|
|
35
|
+
patch(oldVNode: T, newVNode: T, currentNode: Node, context: RenderRuntimeContext): Node;
|
|
36
|
+
unmount(vnode: T, currentNode: Node, context: RenderRuntimeContext): void;
|
|
37
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ComponentNode, SlotProvider } from './vnode';
|
|
2
|
+
export { ElementRenderStrategy } from './renderer/element-strategy';
|
|
3
|
+
export type { ComponentInstance, RenderRuntimeContext, RenderStrategy, Renderable, RendererHost, } from './renderer/types';
|
|
4
|
+
import type { RenderRuntimeContext, RenderStrategy, Renderable } from './renderer/types';
|
|
5
|
+
export declare class RendererContext {
|
|
6
|
+
private readonly strategies;
|
|
7
|
+
constructor();
|
|
8
|
+
mount(vnode: Renderable, context: RenderRuntimeContext): Node;
|
|
9
|
+
patch(oldVNode: Renderable, newVNode: Renderable, currentNode: Node, context: RenderRuntimeContext): Node;
|
|
10
|
+
unmount(vnode: Renderable, currentNode: Node, context: RenderRuntimeContext): void;
|
|
11
|
+
private findStrategy;
|
|
12
|
+
}
|
|
13
|
+
export declare class TextRenderStrategy implements RenderStrategy<string> {
|
|
14
|
+
matches(vnode: Renderable): vnode is string;
|
|
15
|
+
mount(vnode: string, context: RenderRuntimeContext): Node;
|
|
16
|
+
patch(oldVNode: string, newVNode: string, currentNode: Node, context: RenderRuntimeContext): Node;
|
|
17
|
+
unmount(): void;
|
|
18
|
+
}
|
|
19
|
+
export declare class ComponentRenderStrategy implements RenderStrategy<ComponentNode> {
|
|
20
|
+
private readonly instances;
|
|
21
|
+
private readonly instanceNodes;
|
|
22
|
+
private readonly emitterUnsubscribers;
|
|
23
|
+
matches(vnode: Renderable): vnode is ComponentNode;
|
|
24
|
+
mount(vnode: ComponentNode, context: RenderRuntimeContext): Node;
|
|
25
|
+
patch(oldVNode: ComponentNode, newVNode: ComponentNode, currentNode: Node, context: RenderRuntimeContext): Node;
|
|
26
|
+
unmount(_vnode: ComponentNode, currentNode: Node, context: RenderRuntimeContext): void;
|
|
27
|
+
private createProps;
|
|
28
|
+
private syncEmitters;
|
|
29
|
+
private clearEmitters;
|
|
30
|
+
private trackInstanceNode;
|
|
31
|
+
private clearInstanceNodes;
|
|
32
|
+
}
|
|
33
|
+
export declare class SlotRenderStrategy implements RenderStrategy<SlotProvider> {
|
|
34
|
+
private readonly renderedChildren;
|
|
35
|
+
matches(vnode: Renderable): vnode is SlotProvider;
|
|
36
|
+
mount(vnode: SlotProvider, context: RenderRuntimeContext): Node;
|
|
37
|
+
patch(oldVNode: SlotProvider, newVNode: SlotProvider, currentNode: Node, context: RenderRuntimeContext): Node;
|
|
38
|
+
unmount(_vnode: SlotProvider, currentNode: Node, context: RenderRuntimeContext): void;
|
|
39
|
+
private resolveChildren;
|
|
40
|
+
private replaceSlotChildren;
|
|
41
|
+
private mountSlotChildren;
|
|
42
|
+
private unmountSlotChildren;
|
|
43
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { ReactiveEffect } from './reactive';
|
|
2
|
+
export interface TemplateBinding {
|
|
3
|
+
node: Text;
|
|
4
|
+
originalText: string;
|
|
5
|
+
effect: ReactiveEffect;
|
|
6
|
+
}
|
|
7
|
+
export declare class TemplateEngine {
|
|
8
|
+
state: object;
|
|
9
|
+
private bindings;
|
|
10
|
+
private readonly templateRegex;
|
|
11
|
+
constructor(state: object);
|
|
12
|
+
/**
|
|
13
|
+
* 解析模板字符串,创建响应式的文本节点
|
|
14
|
+
* @param text 包含模板表达式的文本字符串
|
|
15
|
+
* @returns 创建的文本节点
|
|
16
|
+
*/
|
|
17
|
+
parseTemplate(text: string): Text;
|
|
18
|
+
/**
|
|
19
|
+
* 设置响应式绑定
|
|
20
|
+
*/
|
|
21
|
+
private setupReactiveBindings;
|
|
22
|
+
/**
|
|
23
|
+
* 计算模板文本的值
|
|
24
|
+
*/
|
|
25
|
+
private evaluateTemplate;
|
|
26
|
+
/**
|
|
27
|
+
* 从状态对象中获取值,支持嵌套属性访问
|
|
28
|
+
*/
|
|
29
|
+
private getValueFromState;
|
|
30
|
+
/**
|
|
31
|
+
* 清除所有模板绑定
|
|
32
|
+
*/
|
|
33
|
+
clearBindings(): void;
|
|
34
|
+
/**
|
|
35
|
+
* 获取当前的绑定数量
|
|
36
|
+
*/
|
|
37
|
+
getBindingCount(): number;
|
|
38
|
+
/**
|
|
39
|
+
* 检查模板是否包含表达式
|
|
40
|
+
*/
|
|
41
|
+
hasExpressions(text: string): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* 获取模板中的所有表达式键
|
|
44
|
+
*/
|
|
45
|
+
extractKeys(text: string): string[];
|
|
46
|
+
/**
|
|
47
|
+
* 计算模板值
|
|
48
|
+
*/
|
|
49
|
+
evaluateTemplateValue(text: string): string;
|
|
50
|
+
}
|