compelem 0.0.0 → 0.1.0-beta

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/CHANGELOG.md ADDED
@@ -0,0 +1 @@
1
+ # Changelog
package/CompElem.d.ts ADDED
@@ -0,0 +1,137 @@
1
+ import { Directive } from "./directive/Directive";
2
+ import { IComponent } from "./IComponent";
3
+ import { Template } from "./render/render";
4
+ import { IRenderContext } from "./render/RenderContext";
5
+ import { TmplFn } from "./types";
6
+ declare const CompElem_base: {
7
+ new (...args: any[]): {
8
+ [x: string]: any;
9
+ render(...args: any): void | Template | Template[] | ((...args: any[]) => (Template | Template[]));
10
+ __expPos: Record<string, import("./types").ExpPos>;
11
+ __expPosMap: Record<string, Record<string, import("./types").ExpPos> | null>;
12
+ __directives: Record<string, Directive>;
13
+ slotComponent: CompElem;
14
+ renderComponent: CompElem;
15
+ renderContext(...args: any): [NodeListOf<ChildNode>, Record<string, import("./types").ExpPos>, Record<string, Record<string, import("./types").ExpPos> | null>];
16
+ updateContext(...args: any): void;
17
+ __updateExpPos(tmpl: Template, _expPos: Record<string, import("./types").ExpPos>): void;
18
+ };
19
+ } & {
20
+ new (): HTMLElement;
21
+ prototype: HTMLElement;
22
+ };
23
+ /**
24
+ * CompElem基类,意为组件元素。提供了基本内置属性及生命周期等必备接口
25
+ * 每个组件都需要继承自该类
26
+ *
27
+ * @author holyhigh2
28
+ */
29
+ export declare abstract class CompElem extends CompElem_base implements IComponent {
30
+ #private;
31
+ static __l_globalRule: HTMLStyleElement;
32
+ __events: Record<string, Array<Node | ((e: Event) => void)>[]>;
33
+ get reactiveData(): Record<string, any>;
34
+ get attrs(): Record<string, string>;
35
+ get props(): Record<string, any>;
36
+ get renderRoot(): HTMLElement;
37
+ get renderRoots(): HTMLElement[];
38
+ get parentComponent(): HTMLElement | null;
39
+ get slotHooks(): Record<string, (...args: any[]) => Template>;
40
+ get styles(): CSSStyleSheet[];
41
+ get isMounted(): boolean;
42
+ get slots(): Record<string, Array<Node>>;
43
+ /**
44
+ * 是否自动插入插槽,如果需要控制插槽类型时,可以设置为false
45
+ */
46
+ static get autoSlot(): boolean;
47
+ /**
48
+ * 组件样式,CSSStyleSheet可动态变更
49
+ */
50
+ static get styles(): Array<string | CSSStyleSheet>;
51
+ static get globalStyles(): Array<string>;
52
+ get css(): string;
53
+ constructor(...args: any[]);
54
+ connectedCallback(): void;
55
+ disconnectedCallback(): void;
56
+ __init(): void;
57
+ /**
58
+ * 初始化属性及状态,该回调内可以访问props和state
59
+ * 此时组件dom并未构建,但已有parent 属性,没有root属性
60
+ */
61
+ connected(): void;
62
+ /**
63
+ * props初始化完成回调
64
+ */
65
+ propsReady(): void;
66
+ /**
67
+ * 每次更新时调用
68
+ */
69
+ abstract render(): Template;
70
+ /**
71
+ * dom渲染完毕后调用,该回调内可以query注解初始化完成
72
+ */
73
+ mounted(): void;
74
+ slotchange(slot: HTMLSlotElement, name: string): void;
75
+ /**
76
+ * 是否需要更新,可获取变更属性
77
+ * 返回true时更新
78
+ */
79
+ shouldUpdate(changed: Record<string, any>): boolean;
80
+ /**
81
+ * 1. 调用render
82
+ * 2. 更新@query/all
83
+ * 3. 更新ref
84
+ * 4. 更新prop到attr的映射
85
+ * @param changed
86
+ */
87
+ updated(changed: Record<string, any>): void;
88
+ /**
89
+ * 抛出自定义事件
90
+ * @param evName 事件名称
91
+ * @param args 自定义参数
92
+ */
93
+ emit(evName: string, arg?: Record<string, any>, options?: {
94
+ event?: Event;
95
+ bubbles?: boolean;
96
+ composed?: boolean;
97
+ }): void;
98
+ /**
99
+ * 在root上绑定事件
100
+ * @param evName
101
+ * @param hook
102
+ */
103
+ on(evName: string, hook: (e: Event) => void): void;
104
+ /**
105
+ * 下一帧执行
106
+ * @param cbk
107
+ */
108
+ nextTick(cbk: () => void): void;
109
+ /**
110
+ * 强制更新一次视图
111
+ */
112
+ forceUpdate(): void;
113
+ /**
114
+ * 由监控变量调用
115
+ * @param stateKey
116
+ * @param ov
117
+ * @param rootStateKey 如果是对象内部属性变更,会返回根属性名
118
+ * @returns
119
+ */
120
+ _notify(ov: any, chain: string[]): void;
121
+ /**
122
+ * @deprecated
123
+ */
124
+ _setParentProps(props: Record<string, any>, attrs?: Record<string, any>): void;
125
+ _updateProps(props: Record<string, any>): void;
126
+ _initProps(props: Record<string, any>, attrs?: Record<string, any>): void;
127
+ /**
128
+ * 绑定slot标签,render时调用
129
+ */
130
+ _bindSlot(slot: HTMLSlotElement, name: string, props: Record<string, any>): void;
131
+ _bindSlotHook(name: string, hook: (...args: any[]) => Template): void;
132
+ _updateSlot(name: string, propName?: string, value?: any): void;
133
+ _asyncDirectives: WeakMap<TmplFn, IRenderContext>;
134
+ renderAsync(cbk: TmplFn, ...args: any[]): void;
135
+ _regDeps(varPath: string, renderContext: CompElem | Directive): void;
136
+ }
137
+ export {};
@@ -0,0 +1,49 @@
1
+ import { Template } from "./render/render";
2
+ /**
3
+ * 组件接口
4
+ * 定义组件属性、生命周期及方法
5
+ * @author holyhigh2
6
+ */
7
+ export interface IComponent {
8
+ get attrs(): Record<string, string>;
9
+ get props(): Record<string, any>;
10
+ get renderRoot(): HTMLElement;
11
+ get renderRoots(): HTMLElement[];
12
+ get parentComponent(): HTMLElement | null;
13
+ get slots(): Record<string, Array<Node>>;
14
+ get slotHooks(): Record<string, (...args: any[]) => Template>;
15
+ get styles(): CSSStyleSheet[];
16
+ get isMounted(): boolean;
17
+ connected(): void;
18
+ propsReady(): void;
19
+ render(): Template;
20
+ mounted(): void;
21
+ shouldUpdate(changed: Record<string, any>): boolean;
22
+ updated(changed: Record<string, any>): void;
23
+ slotchange(slot: HTMLSlotElement, name: string): void;
24
+ /**
25
+ * 抛出自定义事件
26
+ * @param evName 事件名称
27
+ * @param args 自定义参数
28
+ */
29
+ emit(evName: string, arg: Record<string, any>, options?: {
30
+ event?: Event;
31
+ bubbles?: boolean;
32
+ composed?: boolean;
33
+ }): void;
34
+ /**
35
+ * 在root上绑定事件
36
+ * @param evName
37
+ * @param hook
38
+ */
39
+ on(evName: string, hook: (e: Event) => void): void;
40
+ /**
41
+ * 下一帧执行
42
+ * @param cbk
43
+ */
44
+ nextTick(cbk: () => void): void;
45
+ /**
46
+ * 强制更新一次视图
47
+ */
48
+ forceUpdate(): void;
49
+ }
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 holyhigh2
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,402 @@
1
+ # CompElem
2
+
3
+ 一个现代化、响应式、快速、轻量的 WebComponent 开发库。为开发者提供丰富、灵活、可扩展的声明式接口
4
+
5
+ ## 概览
6
+
7
+ CompElem 基于 Class 进行构建,该模型允许开发者使用装饰器进行声明式编码,核心特性包括:
8
+
9
+ - 类 JSX 的原生模板系统
10
+ - 丰富的装饰器及指令
11
+ - 可选的生命周期
12
+ - 原生插槽系统
13
+ - 响应式域样式
14
+ - ...
15
+
16
+ 创建一个 WebComponent 总会从声明一个组件元素(CompElem 子类)开始
17
+
18
+ ```ts
19
+ const Slogan = ["complete", "componentize", "compact", "companion"];
20
+ @tag("page-test")
21
+ export class PageTest extends CompElem {
22
+ //////////////////////////////////// props
23
+ @prop arg: any;
24
+
25
+ @state colorR = (Math.random() * 255) % 255 >> 0;
26
+ @state colorG = (Math.random() * 255) % 255 >> 0;
27
+ @state colorB = (Math.random() * 255) % 255 >> 0;
28
+ @state rotation = 0;
29
+
30
+ //////////////////////////////////// computed
31
+ @computed
32
+ get color() {
33
+ return `linear-gradient(90deg,rgb(${this.colorR},${this.colorG},${
34
+ this.colorB
35
+ }), rgb(${255 - this.colorR},${255 - this.colorG},${255 - this.colorB}));`;
36
+ }
37
+
38
+ //////////////////////////////////// watch
39
+ @watch("rotation")
40
+ function(nv: number) {
41
+ console.log(nv);
42
+ }
43
+
44
+ //////////////////////////////////// styles
45
+ //静态样式
46
+ static get styles(): Array<string | CSSStyleSheet> {
47
+ return [
48
+ `:host{
49
+ font-size:16px;
50
+ }...`,
51
+ ];
52
+ }
53
+ //动态样式
54
+ get css() {
55
+ return `h2,p,i,h3{
56
+ background-image:${this.color}
57
+ filter:hue-rotate(${this.rotation}deg)
58
+ }`;
59
+ }
60
+
61
+ @query('i[name="text"]')
62
+ text: HTMLElement;
63
+ sloganIndex = 0;
64
+
65
+ //////////////////////////////////// lifecycles
66
+ mounted(): void {
67
+ setInterval(() => {
68
+ this.rotation += 1;
69
+ }, 24);
70
+
71
+ setInterval(() => {
72
+ this.text.classList.add("hide");
73
+ setTimeout(() => {
74
+ this.text.innerHTML = Slogan[this.sloganIndex % 4];
75
+ this.sloganIndex++;
76
+ this.text.classList.remove("hide");
77
+ }, 500);
78
+ }, 5000);
79
+ }
80
+ render(): Template {
81
+ return html`<div>
82
+ <i>Welcome to</i>
83
+ <br />
84
+ <h2>CompElem</h2>
85
+ <br />
86
+ <i>A modern, reactive, fast and lightweight library</i>
87
+ <br />
88
+ <i>for building</i>
89
+ <h3>Web Components</h3>
90
+ <p>&lt;c-element&gt; <i name="text">...</i> &lt;/c-element&gt;</p>
91
+ ${this.arg}
92
+ </div>`;
93
+ }
94
+ }
95
+ ```
96
+
97
+ 而后即可在 HTML 中直接使用,与使用一个原生元素如 DIV 没有任何区别
98
+
99
+ ```html
100
+ <body>
101
+ <page-test arg="args..."></page-test>
102
+ </body>
103
+ ```
104
+
105
+ 当然,也可以直接嵌入其他 UI 库中只要引入编译后的 js 即可
106
+
107
+ ## APIs
108
+
109
+ - ### 视图模板
110
+ 使用`render()`函数定义组件视图模板
111
+ ```ts
112
+ render(): Template{
113
+ return html`<div>Hello CompElem</div>`
114
+ }
115
+ ```
116
+ - ### 视图模板-属性表达式
117
+
118
+ 通过再视图模板中插入表达式可以实现动态视图,表达式通过在不同位置使用分为不同类型见(#### 指令类型)。其中属性表达式根据前缀分为
119
+
120
+ | 前缀 | 描述 | 示例 |
121
+ | ---- | ------------------------------------------------------------- | -------------------------------------- |
122
+ | @ | 事件属性,可用于任何标签 | `<div @click="${this.onClick}">` |
123
+ | . | 参数属性,仅用于给组件标签传递参数 | `<l-input .value="${this.text}">` |
124
+ | ? | 可选属性,用于 disabled/readonly 等 toggle 类属性 | `<input ?disabled="${this.disabled}">` |
125
+ | \* | 引用属性,表达式求值后才会设置该属性。常用于 SVG 相关属性设置 | `<circle *r="${this.r}">` |
126
+
127
+ > 引用属性可通过属性参数进行格式转换,如
128
+
129
+ ```ts
130
+ render(): Template{
131
+ return html`<svg *view-box:camel="">...</svg>`// <svg viewBox="">
132
+ }
133
+ ```
134
+
135
+ 支持格式包括:
136
+
137
+ - camel 驼峰式
138
+ - kebab 短横线
139
+ - snake 下划线
140
+
141
+ - ### 样式
142
+ 使用静态函数定义组件样式或全局样式(如弹框)
143
+ ```ts
144
+ static get styles(): Array<string | CSSStyleSheet> {
145
+ return [];
146
+ }
147
+ static get globalStyles(): Array<string> {
148
+ return [];
149
+ }
150
+ ```
151
+ 对于需要动态控制 host 元素样式可以使用组件实例 getter
152
+ ```ts
153
+ get css():string{
154
+ return `:host{
155
+ ${this.border?'border: 1px solid rgb(var(--l-color-border-secondary)); ':''}
156
+ }`
157
+ }
158
+ ```
159
+ - ### 属性
160
+
161
+ 属性是由组件外部提供参数的响应变量,可通过`@prop`注解定义
162
+
163
+ ```ts
164
+ @prop({ type: Boolean }) loading = false;//显式定义属性类型
165
+ @prop round = true;//通过默认值自动推断属性类型
166
+ @prop({ type: [Boolean,String] }) round = true;//多种类型使用数组定义
167
+ @prop({ type: Array }) datalist: Array<string>;//没有默认值必须显式指定属性类型
168
+ @prop({ type: [String, Number], sync: true }) //通过get/set设置属性
169
+ get value() {
170
+ return this.__innerValue ?? ''
171
+ }
172
+ set value(v: any) {
173
+ this.__innerValue = v
174
+ if (isNil(v)) {
175
+ this.__innerValue = '';
176
+ }
177
+ }
178
+ ```
179
+
180
+ 属性可以在组件内修改但默认不会同步父组件,除非显式指定`sync`或自行 emit update 事件
181
+ 全部注解参数见 `PropOption`
182
+
183
+ - ### 状态
184
+ 状态是仅由组件内部初始化的响应变量,可通过`@state`注解定义
185
+ ```ts
186
+ @state hasLeft = false;//定义状态
187
+ @state({//自定义变化判断
188
+ hasChanged(nv: any[], ov: any[]) {
189
+ return isEqual(nv , ov)
190
+ }
191
+ }) private nodes: Array<Record<string, any>>;
192
+ ```
193
+ 状态仅能在组件内修改
194
+ 全部注解参数见 `StateOption`
195
+ - ### 状态监视
196
+
197
+ 使用`@watch`注解可以对属性/状态进行变化监视
198
+
199
+ ```ts
200
+ @prop width = "auto";
201
+
202
+ @watch("width", { immediate: true })
203
+ watchWidth(nv: string, ov: string, sourceName: string) {
204
+ this.style.width = nv;
205
+ }
206
+ ```
207
+
208
+ 对于同类属性共享处理逻辑的监视,可以批量处理
209
+
210
+ ```ts
211
+ @watch(['height', 'minHeight', 'maxHeight'], { immediate: true })
212
+ watchHeight(nv: string, ov: string, sourceName: string) {
213
+ this.style[srcName] = nv;
214
+ }
215
+ ```
216
+
217
+ - ### 计算状态
218
+ 计算状态会缓存 return 结果,只有当内部使用的任意属性/状态发生变化时才会重新计算
219
+ 使用`@computed`注解的 Getter,如
220
+ ```ts
221
+ @computed
222
+ get hasHeader() {
223
+ return !isEmpty(this.slots.header) || !!this.header
224
+ }
225
+ ```
226
+ - ### 节点引用
227
+ 使用`@query/all`注解及`ref`属性
228
+ ```ts
229
+ //query
230
+ @query('l-icon')
231
+ iconEl: HTMLElement
232
+ //ref
233
+ refNode: HTMLElement
234
+ ```
235
+ ```ts
236
+ divRef = createRef<HTMLDivElement>();
237
+ //视图片段
238
+ return html` <l-icon></l-icon>
239
+ <div ref="${divRef}"></div>`;
240
+ ```
241
+ - ### 内置属性及函数
242
+ - `readonly` parent 父组件引用,可能为空
243
+ - `readonly` el/els 根元素/根元素列表
244
+ - `readonly` slots 插槽元素
245
+ - `readonly` slotHooks 动态插槽钩子
246
+ - `readonly` styles 组件样式对象列表
247
+ - `readonly` attrs 组件特性
248
+ - `readonly` props 组件属性
249
+ - slotComponent 所在插槽组件
250
+ - on()
251
+ - emit()
252
+ - nextTick()
253
+ - forceUpdate()
254
+
255
+ ## 组件渲染流程
256
+
257
+ CompElem 组件既可以在 CompElem 环境内调用,也可以直接在原生环境调用,区别只是原生环境无法像组件传`递类型参数`。流程如下:
258
+
259
+ > 创建流程
260
+
261
+ | 功能 | | 生命周期 |
262
+ | ------------------------------------------------------------ | --- | ----------- |
263
+ | 1. 创建组件实例,完成类属性默认值设置(prop/state/...) | | |
264
+ | 2. 初始化类全局样式(仅一次)及 实例样式(产生 styles 数组) | | |
265
+ | 3. 创建 shadowRoot 并挂载组件样式 | | constructor |
266
+ | 4. 绑定 parent | | connected |
267
+ | 5. 获取 this.attribute 及 parentProps 进行验证及初始化 props | | propsReady |
268
+ | 6. 注入 link 外部样式表 | | |
269
+ | 7. 渲染 render 及依赖绑定 | | render |
270
+ | 8. 绑定 el 及 els | | |
271
+ | 9. 执行 ref | | |
272
+ | 10. 执行 @query 注解 | | |
273
+ | 11. 执行 @watch(immediate) 注解 | | |
274
+ | 12. 执行 @event 注解 | | mounted |
275
+ | 13. 执行 slot filter / 动态 slot | | slotchange |
276
+
277
+ > 更新流程【普通】
278
+
279
+ | 功能 | 生命周期 |
280
+ | ------------------------------ | ------------ |
281
+ | 1. 父组件 props 变更【或】 | propsReady |
282
+ | 1. 子组件 state 变更【或】 | |
283
+ | 2. 执行@watch 注解 | |
284
+ | 3. 合并变更内容并判断是否更新 | shouldUpdate |
285
+ | 4. 更新依赖域指令(非 render) | |
286
+ | 5. 更新动态 slot | |
287
+ | 6. 执行 ref | |
288
+ | 7. 执行@query 注解 | update |
289
+
290
+ > 更新流程【强制】
291
+
292
+ | 功能 | 生命周期 |
293
+ | ------------------ | -------- |
294
+ | 1. forceUpdate | |
295
+ | 2. 渲染 render | render |
296
+ | 3. 执行@query 注解 | update |
297
+
298
+ ## 插槽 Slot
299
+
300
+ #### 定义插槽
301
+
302
+ 使用原生 `<slot></slot>` 标签来嵌入插槽,可以通过`node-filter`属性过滤插槽内容
303
+
304
+ ```html
305
+ <slot
306
+ .node-filter="${{
307
+ type: [HTMLElement, CompElem],
308
+ maxCount:1
309
+ }}"
310
+ ></slot>
311
+ <!-- 或使用函数精细控制 -->
312
+ <slot .node-filter="${(nodes:Node[])=>Node[]}"></slot>
313
+ ```
314
+
315
+ #### 插入节点(静态)
316
+
317
+ ```html
318
+ <l-tooltip>
319
+ <l-button>默认插槽内容</l-button>
320
+ <div slot="content">命名插槽内容</div>
321
+ </l-tooltip>
322
+ ```
323
+
324
+ #### 插入节点(动态)
325
+
326
+ 动态内容插入仅可在 CompElem 组件中编码,可以通过组件注入参数动态生成插槽内容
327
+
328
+ ```ts
329
+ //仅可用于CompElem组件中
330
+ return html` <l-tooltip>
331
+ //动态内容通过slot指令定义 ${slot(
332
+ (args: Record<string, any>) => html`
333
+ <div>我是动态内容-${args.data.id}</div>
334
+ `,
335
+ "content"
336
+ )}
337
+ </l-tooltip>`;
338
+ ```
339
+
340
+ 在`slot`标签上注入参数
341
+
342
+ ```html
343
+ <slot .data="${this.row}"></slot>
344
+ ```
345
+
346
+ **_注意_**,动态插槽必须关闭自动插槽,否则无效
347
+
348
+ ```ts
349
+ static get autoSlot() {
350
+ return false;
351
+ }
352
+ ```
353
+
354
+ ## 指令 Directive
355
+
356
+ 指令用于分支/循环/动态插槽等结构及隐藏显示等
357
+
358
+ #### 指令类型
359
+
360
+ 不同的指令类型限制了指令仅能用于对应的插入点
361
+ |指令|插入位置|描述|示例|
362
+ |-------|-------|-------|-------|
363
+ |ATTR|特性|可用于任何特性值之中,仅能插入一个|`attr="${xxx}"`|
364
+ |PROP|属性|可用于任何属性值之中,必须是组件标签,仅能插入一个|`.value="${xxx}"`|
365
+ |TEXT|文本|标签体内,可插入多个|`<div>${xx1}${xx2}${...}</div>`|
366
+ |CLASS|样式类|用于 class 属性值中,仅能插入一个|`class="a ${b}"`|
367
+ |STYLE|样式规则|用于 style 属性值中,仅能插入一个|`style="a:1;${b}"`|
368
+ |SLOT|插槽|与 TEXT 类似,但标签必须是组件||
369
+ |TAG|标签|直接插入在节点标签上|`<div a="b" ${show(..)}>`|
370
+
371
+ #### 内置指令
372
+
373
+ | 指令 | 类型 | 描述 | 示例 |
374
+ | ------- | --------- | ----------------------------------------------------------- | ------------------------------------------------------ |
375
+ | bind | TAG | 绑定属性/特性到标签上,根据标签类型及组件 prop 定义自动判断 | `<div a="b" ${bind(obj)}>` |
376
+ | show | TAG | 隐藏/显示标签(基于 display) | `<div a="b" ${show(visible)}>` |
377
+ | model | TAG | 双向绑定 | `<div a="b" ${model(xx)}>` |
378
+ | classes | CLASS | 绑定样式类属性,支持对象/数组/字符串。可以和静态字符混用 | `<div class="otherClass ${classes(obj)}>"` |
379
+ | styles | STYLE | 绑定样式规则属性,支持对象/字符串。可以和静态字符混用 | `<div style="a:b;${styles(obj)}>"` |
380
+ | forEach | TEXT/SLOT | 输出循环结构 | `...>${forEach(ary,(item)=>html`...`)}<...` |
381
+ | ifTrue | TEXT/SLOT | 当条件为 true 时输出模板内容 | `...>${ifTrue(condition,()=>html`...`)}<...` |
382
+ | ifElse | TEXT/SLOT | 当条件为 true/false 时输出对应模板内容 | ` ...>${ifElse(condition,()=>html``,()=>html``)}<... ` |
383
+ | when | TEXT/SLOT | 多条件分支,支持 switch/ifelse 两种模式 | ` ...>${when(condition,{c1:()=>html``,c2:...})}<... ` |
384
+ | slot | SLOT | 动态插槽 | ` ...>${slot((args) => html``)}<... ` |
385
+
386
+ ## 装饰器 Decorator
387
+
388
+ - @state 定义组件内状态属性。可选参数{prop},可指定 propName 初始化值
389
+ - @prop 定义父组件参数,默认不可修改。可选参数{type,required,sync,getter,setter}
390
+ > 设置 getter/setter 后,该属性的`@watch` 将会失效
391
+ - @query/queryAll 定义 CssSelector 查询结果
392
+ - @tag 自定义组件的标签名
393
+ - @event 定义全局事件
394
+ - @watch 监控 state/prop 变更
395
+
396
+ ## 事件
397
+
398
+ 事件分为三类
399
+
400
+ 1. 原生事件 —— `<div @click="..."`,监听器回调参数返回原生事件对象
401
+ 2. 组件自定义事件 —— `<l-select @change="..."`,监听器回调参数返回`CustomEvent`事件对象
402
+ 3. 扩展原生事件 —— `<div @resize="..."`,监听器回调参数返回`CustomEvent`事件对象
@@ -0,0 +1,34 @@
1
+ import { CompElem } from "../CompElem";
2
+ export declare enum DecoratorType {
3
+ CLASS = "class",
4
+ FIELD = "field",
5
+ METHOD = "method"
6
+ }
7
+ /**
8
+ * 用于构造装饰器
9
+ * @author holyhigh2
10
+ */
11
+ export declare abstract class Decorator {
12
+ /**
13
+ * 装饰器使用范围,超出范围会报错
14
+ */
15
+ abstract get targets(): Array<DecoratorType>;
16
+ /**
17
+ * 构造会传递自定义参数
18
+ * @param args 自定义参数
19
+ */
20
+ /**
21
+ * 返回用于识别唯一实例的key,比如@watch(a.b.c)中的变量路径就会作为唯一key
22
+ * @param args
23
+ */
24
+ abstract created(component: CompElem, ...args: any[]): any;
25
+ /**
26
+ * 执行时机与组件一致
27
+ * @param component 组件实例
28
+ * @param setReactive 为实例设置响应属性,注意,仅是设置到了instance.reactiveData中并非this.key。如需实现this访问,可自行定义组件的properties
29
+ * @param args 装饰器函数参数
30
+ */
31
+ abstract propsReady(component: CompElem, setReactive: (key: string, value: any) => any, ...args: any[]): any;
32
+ abstract mounted(component: CompElem, setReactive: (key: string, value: any) => any, ...args: any[]): any;
33
+ abstract updated(component: CompElem, changed: Record<string, any>): any;
34
+ }
@@ -0,0 +1,32 @@
1
+ import { Constructor } from './../types';
2
+ /*************************************************************
3
+ * 装饰器
4
+ * @author holyhigh2
5
+ *************************************************************/
6
+ import { CompElem } from "../CompElem";
7
+ import { Decorator } from "./Decorator";
8
+ export declare const GetKeyFnName = "getKey";
9
+ export declare const DecoratorsKey = "__decorators";
10
+ /**
11
+ * 装饰器包装类
12
+ * 用于框架内部,表示class上的一个装饰器属性定义
13
+ * 该定义在实例初始化时会产生装饰器实例属性
14
+ */
15
+ export declare class DecoratorWrapper {
16
+ args: any[];
17
+ metadata: any[];
18
+ decoratorClass: Constructor<Decorator>;
19
+ instanceMap: WeakMap<CompElem, Decorator>;
20
+ key?: string;
21
+ constructor(args: any[], metadata: any[], decoratorClass: Constructor<Decorator>);
22
+ create(comp: CompElem): void;
23
+ propsReady(comp: CompElem, setReactive: (key: string, value: any) => any): void;
24
+ mounted(comp: CompElem, setReactive: (key: string, value: any) => any): void;
25
+ updated(comp: CompElem, changed: Record<string, any>): void;
26
+ }
27
+ /**
28
+ * 该函数用于创建一个装饰器
29
+ * @param decoClass 装饰器构造
30
+ * @returns 装饰器函数
31
+ */
32
+ export declare function decorator<T extends Array<any>>(decoClass: Constructor<Decorator>): (...args: T) => (...metadata: any[]) => void;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * 定义计算属性
3
+ * 计算属性会自动跟踪get函数内的state/prop,并在变动时自动变更
4
+ * 只能应用在一个非静态get属性上
5
+ * @param source 变量名(数组),支持访问链
6
+ * @param immediate 立即执行
7
+ * @param deep 深度监控
8
+ */
9
+ export declare function computed(arg?: any): void;
10
+ export declare function computed(target: any, propertyKey: string): void;