compelem 0.2.1-beta → 0.2.3-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/CompElem.d.ts CHANGED
@@ -71,7 +71,7 @@ export declare class CompElem extends CompElem_base implements IComponent {
71
71
  * dom渲染完毕后调用,该回调内可以query注解初始化完成
72
72
  */
73
73
  mounted(): void;
74
- slotchange(slot: HTMLSlotElement, name: string): void;
74
+ slotChange(slot: HTMLSlotElement, name: string): void;
75
75
  /**
76
76
  * 是否需要更新,可获取变更属性
77
77
  * 返回true时更新
package/IComponent.d.ts CHANGED
@@ -20,7 +20,7 @@ export interface IComponent {
20
20
  mounted(): void;
21
21
  shouldUpdate(changed: Record<string, any>): boolean;
22
22
  updated(changed: Record<string, any>): void;
23
- slotchange(slot: HTMLSlotElement, name: string): void;
23
+ slotChange(slot: HTMLSlotElement, name: string): void;
24
24
  /**
25
25
  * 抛出自定义事件
26
26
  * @param evName 事件名称
package/README.md CHANGED
@@ -1,111 +1,101 @@
1
1
  # CompElem
2
+ 一个现代化、响应式、快速、轻量的WebComponent开发库。为开发者提供丰富、灵活、可扩展的声明式接口
2
3
 
3
- 一个现代化、响应式、快速、轻量的 WebComponent 开发库。为开发者提供丰富、灵活、可扩展的声明式接口
4
-
5
- ## 概览
6
-
4
+ ## 概览
7
5
  CompElem 基于 Class 进行构建,该模型允许开发者使用装饰器进行声明式编码,核心特性包括:
8
-
9
- - 类 JSX 的原生模板系统
6
+ - 类JSX的原生模板系统
10
7
  - 丰富的装饰器及指令
11
8
  - 可选的生命周期
12
9
  - 原生插槽系统
13
10
  - 响应式域样式
14
11
  - ...
15
12
 
16
- 创建一个 WebComponent 总会从声明一个组件元素(CompElem 子类)开始
17
-
13
+ 创建一个WebComponent总会从声明一个组件元素(CompElem子类)开始
18
14
  ```ts
19
- const Slogan = ["complete", "componentize", "compact", "companion"];
15
+ const Slogan = ['complete', 'componentize', 'compact', 'companion']
20
16
  @tag("page-test")
21
17
  export class PageTest extends CompElem {
22
18
  //////////////////////////////////// props
23
- @prop arg: any;
19
+ @prop arg:any
24
20
 
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;
21
+ @state colorR = Math.random() * 255 % 255 >> 0;
22
+ @state colorG = Math.random() * 255 % 255 >> 0;
23
+ @state colorB = Math.random() * 255 % 255 >> 0;
24
+ @state rotation = 0
29
25
 
30
26
  //////////////////////////////////// computed
31
27
  @computed
32
28
  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}));`;
29
+ return `linear-gradient(90deg,rgb(${this.colorR},${this.colorG},${this.colorB}), rgb(${255 - this.colorR},${255 - this.colorG},${255 - this.colorB}));`
36
30
  }
37
31
 
38
32
  //////////////////////////////////// watch
39
- @watch("rotation")
40
- function(nv: number) {
41
- console.log(nv);
33
+ @watch('rotation')
34
+ function(nv:number) {
35
+ console.log(nv)
42
36
  }
43
37
 
44
38
  //////////////////////////////////// styles
45
39
  //静态样式
46
40
  static get styles(): Array<string | CSSStyleSheet> {
47
- return [
48
- `:host{
41
+ return [`:host{
49
42
  font-size:16px;
50
- }...`,
51
- ];
43
+ }...`];
52
44
  }
53
45
  //动态样式
54
46
  get css() {
55
47
  return `h2,p,i,h3{
56
48
  background-image:${this.color}
57
49
  filter:hue-rotate(${this.rotation}deg)
58
- }`;
50
+ }`
59
51
  }
60
52
 
61
53
  @query('i[name="text"]')
62
- text: HTMLElement;
63
- sloganIndex = 0;
54
+ text: HTMLElement
55
+ sloganIndex = 0
64
56
 
65
57
  //////////////////////////////////// lifecycles
66
58
  mounted(): void {
67
59
  setInterval(() => {
68
- this.rotation += 1;
60
+ this.rotation += 1
69
61
  }, 24);
70
62
 
71
63
  setInterval(() => {
72
- this.text.classList.add("hide");
64
+ this.text.classList.add('hide')
73
65
  setTimeout(() => {
74
- this.text.innerHTML = Slogan[this.sloganIndex % 4];
75
- this.sloganIndex++;
76
- this.text.classList.remove("hide");
66
+ this.text.innerHTML = Slogan[this.sloganIndex % 4]
67
+ this.sloganIndex++
68
+ this.text.classList.remove('hide')
77
69
  }, 500);
78
70
  }, 5000);
79
71
  }
80
72
  render(): Template {
81
73
  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>`;
74
+ <i>Welcome to</i>
75
+ <br>
76
+ <h2>CompElem</h2>
77
+ <br>
78
+ <i>A modern, reactive, fast and lightweight library</i>
79
+ <br>
80
+ <i>for building</i>
81
+ <h3>Web Components</h3>
82
+ <p>
83
+ &lt;c-element&gt; <i name="text">...</i> &lt;/c-element&gt;
84
+ </p>
85
+ ${this.arg}
86
+ </div>`
93
87
  }
94
88
  }
95
89
  ```
96
-
97
- 而后即可在 HTML 中直接使用,与使用一个原生元素如 DIV 没有任何区别
98
-
90
+ 而后即可在HTML中直接使用,与使用一个原生元素如DIV没有任何区别
99
91
  ```html
100
92
  <body>
101
- <page-test arg="args..."></page-test>
93
+ <page-test arg="args..."></page-test>
102
94
  </body>
103
95
  ```
96
+ 当然,也可以直接嵌入其他UI库中只要引入编译后的js即可
104
97
 
105
- 当然,也可以直接嵌入其他 UI 库中只要引入编译后的 js 即可
106
-
107
- ## APIs
108
-
98
+ ## APIs
109
99
  - ### 视图模板
110
100
  使用`render()`函数定义组件视图模板
111
101
  ```ts
@@ -180,6 +170,22 @@ export class PageTest extends CompElem {
180
170
  属性可以在组件内修改但默认不会同步父组件,除非显式指定`sync`或自行 emit update 事件
181
171
  全部注解参数见 `PropOption`
182
172
 
173
+ > 在某些无法使用装饰器的场景中(如MixinClass),可以使用函数`makeProp(...)`定义prop
174
+ ```ts
175
+ export function Loadable<T extends Constructor<any>>(spuerClass: T) {
176
+ return class Loadable extends spuerClass {
177
+ //declare a prop
178
+ name: string
179
+
180
+ constructor(...args: any[]) {
181
+ super()
182
+ //make the prop reactive
183
+ Decorator.call(this, prop, 'name', { type: String })
184
+ }
185
+ }
186
+ }
187
+ ```
188
+
183
189
  - ### 状态
184
190
  状态是仅由组件内部初始化的响应变量,可通过`@state`注解定义
185
191
  ```ts
@@ -239,18 +245,19 @@ export class PageTest extends CompElem {
239
245
  <div ref="${divRef}"></div>`;
240
246
  ```
241
247
  - ### 内置属性及函数
242
- - `readonly` parent 父组件引用,可能为空
243
- - `readonly` el/els 根元素/根元素列表
244
- - `readonly` slots 插槽元素
245
- - `readonly` slotHooks 动态插槽钩子
248
+ - `readonly` parentComponent 父组件引用,可能为空
249
+ - `readonly` renderRoot/renderRoots 渲染根元素/渲染根元素列表
250
+ - `readonly` shadowRoot 阴影DOM
251
+ - `readonly` slots 插槽元素映射
252
+ - `readonly` slotHooks 动态插槽钩子映射
246
253
  - `readonly` styles 组件样式对象列表
247
254
  - `readonly` attrs 组件特性
248
255
  - `readonly` props 组件属性
249
256
  - slotComponent 所在插槽组件
250
- - on()
251
- - emit()
252
- - nextTick()
253
- - forceUpdate()
257
+ - on(evName: string, hook: (e: Event) => void) 在root元素上绑定事件
258
+ - emit(evName: string, arg: Record<string, any>, options?: {event?: Event;bubbles?: boolean;composed?: boolean;}) 抛出自定义事件
259
+ - nextTick(cbk: () => void) 下一帧执行函数
260
+ - forceUpdate() 强制更新一次视图
254
261
 
255
262
  ## 组件渲染流程
256
263
 
@@ -263,23 +270,23 @@ CompElem 组件既可以在 CompElem 环境内调用,也可以直接在原生
263
270
  | 1. 创建组件实例,完成类属性默认值设置(prop/state/...) | | |
264
271
  | 2. 初始化类全局样式(仅一次)及 实例样式(产生 styles 数组) | | |
265
272
  | 3. 创建 shadowRoot 并挂载组件样式 | | constructor |
266
- | 4. 绑定 parent | | connected |
267
- | 5. 获取 this.attribute 及 parentProps 进行验证及初始化 props | | propsReady |
273
+ | 4. 绑定 parentComponent | | connected |
274
+ | 5. 获取 attrs 及 parentProps 进行验证及初始化 props | | propsReady |
268
275
  | 6. 注入 link 外部样式表 | | |
269
276
  | 7. 渲染 render 及依赖绑定 | | render |
270
- | 8. 绑定 elels | | |
277
+ | 8. 绑定 renderRootrenderRoots | | |
271
278
  | 9. 执行 ref | | |
272
279
  | 10. 执行 @query 注解 | | |
273
280
  | 11. 执行 @watch(immediate) 注解 | | |
274
281
  | 12. 执行 @event 注解 | | mounted |
275
- | 13. 执行 slot filter / 动态 slot | | slotchange |
282
+ | 13. 执行 slot filter / 动态 slot | | slotChange |
276
283
 
277
284
  > 更新流程【普通】
278
285
 
279
286
  | 功能 | 生命周期 |
280
287
  | ------------------------------ | ------------ |
281
288
  | 1. 父组件 props 变更【或】 | propsReady |
282
- | 1. 子组件 state 变更【或】 | |
289
+ | 1. 子组件 states 变更【或】 | |
283
290
  | 2. 执行@watch 注解 | |
284
291
  | 3. 合并变更内容并判断是否更新 | shouldUpdate |
285
292
  | 4. 更新依赖域指令(非 render) | |
@@ -374,7 +381,7 @@ static get autoSlot() {
374
381
  | ------- | --------- | ----------------------------------------------------------- | ------------------------------------------------------ |
375
382
  | bind | TAG | 绑定属性/特性到标签上,根据标签类型及组件 prop 定义自动判断 | `<div a="b" ${bind(obj)}>` |
376
383
  | show | TAG | 隐藏/显示标签(基于 display) | `<div a="b" ${show(visible)}>` |
377
- | model | TAG | 双向绑定 | `<div a="b" ${model(xx)}>` |
384
+ | model | TAG | 双向绑定 | `<div a="b" ${model(xx,modelPath?)}>` |
378
385
  | classes | CLASS | 绑定样式类属性,支持对象/数组/字符串。可以和静态字符混用 | `<div class="otherClass ${classes(obj)}>"` |
379
386
  | styles | STYLE | 绑定样式规则属性,支持对象/字符串。可以和静态字符混用 | `<div style="a:b;${styles(obj)}>"` |
380
387
  | forEach | TEXT/SLOT | 输出循环结构 | `...>${forEach(ary,(item)=>html`...`)}<...` |
@@ -392,6 +399,14 @@ static get autoSlot() {
392
399
  - @tag 自定义组件的标签名
393
400
  - @event 定义全局事件
394
401
  - @watch 监控 state/prop 变更
402
+ - @computed 计算属性,仅在响应变量变更时更新缓存值
403
+
404
+ > 装饰器还可通过函数方式进行调用,如
405
+ > ```ts
406
+ > //Decorator.call(class, decorator, fieldName, ...args)
407
+ > Decorator.call(this, prop, 'name', { type: String })
408
+ > ```
409
+ > **注意**,调用入口必须放在类的构造函数中
395
410
 
396
411
  ## 事件
397
412
 
@@ -399,4 +414,4 @@ static get autoSlot() {
399
414
 
400
415
  1. 原生事件 —— `<div @click="..."`,监听器回调参数返回原生事件对象
401
416
  2. 组件自定义事件 —— `<l-select @change="..."`,监听器回调参数返回`CustomEvent`事件对象
402
- 3. 扩展原生事件 —— `<div @resize="..."`,监听器回调参数返回`CustomEvent`事件对象
417
+ 3. 扩展原生事件 —— `<div @resize="..."`,监听器回调参数返回`CustomEvent`事件对象
@@ -9,6 +9,14 @@ export declare enum DecoratorType {
9
9
  * @author holyhigh2
10
10
  */
11
11
  export declare abstract class Decorator {
12
+ /**
13
+ * 通过函数方式进行装饰器调用
14
+ * @param target 所在类
15
+ * @param deco 装饰器函数
16
+ * @param fieldName 装饰器应用的字段名/函数名/函数
17
+ * @param args 不定参数
18
+ */
19
+ static call(target: any, deco: Function, fieldName: string | Function, ...args: any[]): void;
12
20
  /**
13
21
  * 装饰器使用范围,超出范围会报错
14
22
  */
@@ -6,7 +6,8 @@ import { Constructor } from './../types';
6
6
  import { CompElem } from "../CompElem";
7
7
  import { Decorator } from "./Decorator";
8
8
  export declare const GetKeyFnName = "getKey";
9
- export declare const DecoratorsKey = "__decorators";
9
+ export declare const _DecoratorsKey = "__decorators";
10
+ export declare const _DecoratorMap: WeakMap<WeakKey, any>;
10
11
  /**
11
12
  * 装饰器包装类
12
13
  * 用于框架内部,表示class上的一个装饰器属性定义
@@ -29,4 +30,4 @@ export declare class DecoratorWrapper {
29
30
  * @param decoClass 装饰器构造
30
31
  * @returns 装饰器函数
31
32
  */
32
- export declare function decorator<T extends Array<any>>(decoClass: Constructor<Decorator>): (...args: T) => (...metadata: any[]) => void;
33
+ export declare function decorator<T extends Array<any>>(decoClass: Constructor<Decorator>): (...args: T) => (...metadata: any[]) => any;
@@ -54,12 +54,5 @@ export type PropOption = {
54
54
  * @param options 可选参数 PropOption,如果type未定义则根据默认值自动推断类型
55
55
  */
56
56
  export declare function prop(options: PropOption): (target: any, propertyKey: any) => void;
57
- export declare function prop(target: any, propertyKey: any): void;
58
- /**
59
- * 同@prop装饰器,但可用于构造器中调用
60
- * @param ctor 类构造函数
61
- * @param propertyKey prop名称
62
- * @param options
63
- */
64
- export declare function makeProp(ctor: Function, propertyKey: string, options?: PropOption): void;
57
+ export declare function prop(target: any, propertyKey: any, options?: PropOption): void;
65
58
  export declare function _getObservedAttrs(ctor: Function): Set<string>;
@@ -22,5 +22,5 @@ export type QueryOption = {
22
22
  */
23
23
  cache?: string;
24
24
  };
25
- export declare const query: (selector: string, cache?: QueryCache | undefined) => (...metadata: any[]) => void;
26
- export declare const queryAll: (selector: string, cache?: QueryCache | undefined) => (...metadata: any[]) => void;
25
+ export declare const query: (selector: string, cache?: QueryCache | undefined) => (...metadata: any[]) => any;
26
+ export declare const queryAll: (selector: string, cache?: QueryCache | undefined) => (...metadata: any[]) => any;
@@ -23,4 +23,4 @@ export type DecoratorWatch = {
23
23
  handler: WatchHandler;
24
24
  options: WatchOptions;
25
25
  };
26
- export declare const watch: (source: string | string[], options?: WatchOptions | undefined) => (...metadata: any[]) => void;
26
+ export declare const watch: (source: string | string[], options?: WatchOptions | undefined, handler?: WatchHandler | undefined) => (...metadata: any[]) => any;
@@ -2,4 +2,4 @@ export declare const enum ModelTriggerType {
2
2
  CHANGE = "change",
3
3
  INPUT = "input"
4
4
  }
5
- export declare const model: (modelValue: any) => import("../directive/index").DirectiveWrapper;
5
+ export declare const model: (modelValue: any, modelPath?: string | undefined) => import("../directive/index").DirectiveWrapper;