compelem 0.1.1-beta → 0.2.1-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
@@ -26,7 +26,7 @@ declare const CompElem_base: {
26
26
  *
27
27
  * @author holyhigh2
28
28
  */
29
- export declare abstract class CompElem extends CompElem_base implements IComponent {
29
+ export declare class CompElem extends CompElem_base implements IComponent {
30
30
  #private;
31
31
  static __l_globalRule: HTMLStyleElement;
32
32
  __events: Record<string, Array<Node | ((e: Event) => void)>[]>;
@@ -66,7 +66,7 @@ export declare abstract class CompElem extends CompElem_base implements ICompone
66
66
  /**
67
67
  * 每次更新时调用
68
68
  */
69
- abstract render(): Template;
69
+ render(): Template;
70
70
  /**
71
71
  * dom渲染完毕后调用,该回调内可以query注解初始化完成
72
72
  */
@@ -55,3 +55,11 @@ export type PropOption = {
55
55
  */
56
56
  export declare function prop(options: PropOption): (target: any, propertyKey: any) => void;
57
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;
65
+ export declare function _getObservedAttrs(ctor: Function): Set<string>;
@@ -17,3 +17,10 @@ export type StateOption = {
17
17
  */
18
18
  export declare function state(target: any, stateKey: any): void;
19
19
  export declare function state(options: StateOption): (target: any, stateKey: any) => void;
20
+ /**
21
+ * 同@state装饰器,但可用于构造器中调用
22
+ * @param ctor 类构造函数
23
+ * @param stateKey state 名称
24
+ * @param options
25
+ */
26
+ export declare function makeState(ctor: Function, stateKey: string, options?: StateOption): void;
package/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  /**
2
- * compelem v0.1.1-beta.1730562219
2
+ * compelem v0.2.1-beta.1731600715
3
3
  * A modern, reactive, fast, lightweight and flexible lib for building web components
4
4
  * @holyhigh2
5
5
  * https://github.com/holyhigh2/compelem
6
6
  */
7
- import { toPath, isObject, isDefined, get, isUndefined, isEmpty, has, concat, set, last, isEqual, startsWith, includes, clone, isFunction, isElement, isArray, initial, find, debounce, throttle, once, remove, map, size, isBlank, join, split, replace, compact, toArray, assign, first, each, isString, kebabCase, closest, bind as bind$1, trim, omitBy, camelCase, isNil, some, isNull, fval, test, cloneDeep, merge, omit, flatMap, groupBy, reject, filter, slice, head, trimStart, trimEnd, replaceAll, snakeCase, toString, findIndex, call } from 'myfx';
7
+ import { toPath, isObject, isDefined, get, isUndefined, isEmpty, has, concat, set, merge, cloneDeep, each, kebabCase, last, isEqual, startsWith, includes, clone, isFunction, isElement, isArray, initial, find, debounce, throttle, once, remove, map, size, isBlank, join, split, replace, compact, toArray, assign, first, isString, closest, bind as bind$1, trim, omitBy, camelCase, isNil, some, isNull, fval, test, omit, flatMap, groupBy, reject, filter, slice, head, trimStart, trimEnd, replaceAll, snakeCase, toString, findIndex, call } from 'myfx';
8
8
 
9
9
  function showError(msg) {
10
10
  console.error(`[CompElem]`, msg);
@@ -16,9 +16,13 @@ function showWarn(...args) {
16
16
  console.warn(`[CompElem]`, ...args);
17
17
  }
18
18
  //为依赖收集提供标准地址
19
- function toUpdatePath(varPath) {
19
+ function _toUpdatePath(varPath) {
20
20
  return toPath(varPath).join("-");
21
21
  }
22
+ //获取父类构造
23
+ function _getSuper(cls) {
24
+ return Object.getPrototypeOf(cls);
25
+ }
22
26
 
23
27
  //装饰器类型
24
28
  var DecoratorType;
@@ -127,6 +131,71 @@ function decorator(decoClass) {
127
131
  };
128
132
  }
129
133
 
134
+ //每个类需要监控的属性
135
+ const ObservedAttrsMap = new WeakMap;
136
+ function prop(options) {
137
+ if (arguments.length === 1) {
138
+ return (target, propertyKey, descriptor) => {
139
+ options.required = options.required || false;
140
+ options.attribute = options.attribute === false ? false : true;
141
+ defineProp(target, propertyKey, options, descriptor);
142
+ };
143
+ }
144
+ let target = arguments[0], propertyKey = arguments[1], descriptor = arguments[2];
145
+ defineProp(target, propertyKey, { type: undefined, required: false, attribute: true }, descriptor);
146
+ }
147
+ function defineProp(target, propertyKey, options, descriptor) {
148
+ if (!/[a-z]/.test(propertyKey[0])) {
149
+ showError(`Prop '${propertyKey}' must be in CamelCase`);
150
+ }
151
+ let attrSet;
152
+ if (!has(target.constructor, '__deco_props')) {
153
+ const mixinProps = {};
154
+ let parentCtor = target.constructor;
155
+ while ((parentCtor = _getSuper(parentCtor)) !== CompElem) {
156
+ merge(mixinProps, parentCtor.__deco_props ? cloneDeep(parentCtor.__deco_props) : {});
157
+ }
158
+ target.constructor.__deco_props = mixinProps;
159
+ attrSet = new Set();
160
+ each(mixinProps, (v, k) => {
161
+ if (v.attribute) {
162
+ let kbb = kebabCase(k);
163
+ attrSet?.add(kbb);
164
+ }
165
+ });
166
+ ObservedAttrsMap.set(target.constructor, attrSet);
167
+ }
168
+ if (descriptor) {
169
+ if (descriptor.get)
170
+ options.getter = descriptor.get;
171
+ if (descriptor.set)
172
+ options.setter = descriptor.set;
173
+ }
174
+ if (options.attribute) {
175
+ let kbb = kebabCase(propertyKey);
176
+ attrSet?.add(kbb);
177
+ }
178
+ target.constructor.__deco_props[propertyKey] = options;
179
+ }
180
+ /**
181
+ * 同@prop装饰器,但可用于构造器中调用
182
+ * @param ctor 类构造函数
183
+ * @param propertyKey prop名称
184
+ * @param options
185
+ */
186
+ function makeProp(ctor, propertyKey, options) {
187
+ if (options) {
188
+ options.required = options.required || false;
189
+ options.attribute = options.attribute === false ? false : true;
190
+ }
191
+ defineProp(ctor.prototype, propertyKey, options || { type: undefined, required: false, attribute: true });
192
+ }
193
+ //内部接口
194
+ const emptySet = new Set;
195
+ function _getObservedAttrs(ctor) {
196
+ return ObservedAttrsMap.get(ctor) ?? emptySet;
197
+ }
198
+
130
199
  /**
131
200
  * 用于提供全局state状态管理
132
201
  * @author holyhigh2
@@ -223,7 +292,7 @@ function reactive(obj, context) {
223
292
  let subChain = concat(chain, [prop]);
224
293
  let subChainStr = subChain.join('-');
225
294
  if (Collector.__renderCollecting) {
226
- Collector.collect(toUpdatePath(subChain));
295
+ Collector.collect(_toUpdatePath(subChain));
227
296
  Collector.setDirectiveQ(subChain);
228
297
  }
229
298
  else if (Collector.__computeCollecting) {
@@ -820,7 +889,6 @@ class CompElem extends RenderContext(HTMLElement) {
820
889
  #slotHooks = {};
821
890
  #slotNodes = {};
822
891
  #mounted = false;
823
- #observedAttrs = new Set();
824
892
  #instanceCss = new CSSStyleSheet();
825
893
  /**
826
894
  * 是否自动插入插槽,如果需要控制插槽类型时,可以设置为false
@@ -888,15 +956,6 @@ class CompElem extends RenderContext(HTMLElement) {
888
956
  });
889
957
  set(this.constructor, '_component_style_attached', styleSheets);
890
958
  }
891
- //observAttrs
892
- let propDefs = get(this.constructor, "__deco_props");
893
- each(propDefs, (def, key) => {
894
- let propDef = propDefs[key];
895
- if (propDef.attribute) {
896
- let kbb = kebabCase(key);
897
- this.#observedAttrs.add(kbb);
898
- }
899
- });
900
959
  /////////////////////////////////////////////////// shadow
901
960
  this.#shadow = this.attachShadow({
902
961
  mode: "open",
@@ -1070,6 +1129,12 @@ class CompElem extends RenderContext(HTMLElement) {
1070
1129
  * props初始化完成回调
1071
1130
  */
1072
1131
  propsReady() { }
1132
+ /**
1133
+ * 每次更新时调用
1134
+ */
1135
+ render() {
1136
+ throw Error(`[CompElem <${this.tagName}>] Missing render()`);
1137
+ }
1073
1138
  /**
1074
1139
  * dom渲染完毕后调用,该回调内可以query注解初始化完成
1075
1140
  */
@@ -1193,7 +1258,7 @@ class CompElem extends RenderContext(HTMLElement) {
1193
1258
  each(chain, (seg) => {
1194
1259
  varPath.push(seg);
1195
1260
  let v = get(this, varPath);
1196
- let pathStr = toUpdatePath(varPath);
1261
+ let pathStr = _toUpdatePath(varPath);
1197
1262
  if (pathStr === "#slots") {
1198
1263
  pathStr = 'slots';
1199
1264
  }
@@ -1618,7 +1683,8 @@ class CompElem extends RenderContext(HTMLElement) {
1618
1683
  #attrChanged(name, oldValue, newValue) {
1619
1684
  if (!this.isMounted)
1620
1685
  return;
1621
- if (this.#observedAttrs.has(name)) {
1686
+ let observedAttrs = _getObservedAttrs(this.constructor);
1687
+ if (observedAttrs.has(name)) {
1622
1688
  if (isNull(newValue)) {
1623
1689
  let propDefs = get(this.constructor, "__deco_props");
1624
1690
  //使用默认值
@@ -2389,33 +2455,6 @@ function event(eventName, options) {
2389
2455
  };
2390
2456
  }
2391
2457
 
2392
- function prop(options) {
2393
- if (arguments.length === 1) {
2394
- return (target, propertyKey, descriptor) => {
2395
- options.required = options.required || false;
2396
- options.attribute = options.attribute === false ? false : true;
2397
- defineProp(target, propertyKey, options, descriptor);
2398
- };
2399
- }
2400
- let target = arguments[0], propertyKey = arguments[1], descriptor = arguments[2];
2401
- defineProp(target, propertyKey, { type: undefined, required: false, attribute: true }, descriptor);
2402
- }
2403
- function defineProp(target, propertyKey, options, descriptor) {
2404
- if (!/[a-z]/.test(propertyKey[0])) {
2405
- showError(`Prop '${propertyKey}' must be in CamelCase`);
2406
- }
2407
- if (!has(target.constructor, '__deco_props')) {
2408
- target.constructor.__deco_props = isEmpty(target.constructor.__deco_props) ? {} : cloneDeep(target.constructor.__deco_props);
2409
- }
2410
- if (descriptor) {
2411
- if (descriptor.get)
2412
- options.getter = descriptor.get;
2413
- if (descriptor.set)
2414
- options.setter = descriptor.set;
2415
- }
2416
- target.constructor.__deco_props[propertyKey] = options;
2417
- }
2418
-
2419
2458
  /**
2420
2459
  * 缓存策略
2421
2460
  */
@@ -2488,10 +2527,24 @@ function state(options) {
2488
2527
  }
2489
2528
  function defineState(target, stateKey, options) {
2490
2529
  if (!has(target.constructor, "__deco_states")) {
2491
- target.constructor.__deco_states = isEmpty(target.constructor.__deco_states) ? {} : cloneDeep(target.constructor.__deco_states);
2530
+ const mixinStates = {};
2531
+ let parentCtor = target.constructor;
2532
+ while ((parentCtor = _getSuper(parentCtor)) !== CompElem) {
2533
+ merge(mixinStates, parentCtor.__deco_states ? cloneDeep(parentCtor.__deco_states) : {});
2534
+ }
2535
+ target.constructor.__deco_states = mixinStates;
2492
2536
  }
2493
2537
  target.constructor.__deco_states[stateKey] = options;
2494
2538
  }
2539
+ /**
2540
+ * 同@state装饰器,但可用于构造器中调用
2541
+ * @param ctor 类构造函数
2542
+ * @param stateKey state 名称
2543
+ * @param options
2544
+ */
2545
+ function makeState(ctor, stateKey, options) {
2546
+ defineState(ctor.prototype, stateKey, options || { prop: "" });
2547
+ }
2495
2548
 
2496
2549
  /**
2497
2550
  * class用注解,用于自动注册自定义组件
@@ -3116,4 +3169,4 @@ class When extends Directive {
3116
3169
  }
3117
3170
  const when = directive(When);
3118
3171
 
3119
- export { CompElem, Decorator, DecoratorType, DecoratorWrapper, DecoratorsKey, Directive, DirectiveUpdateTag, DirectiveWrapper, EnterPoint, EnterPointType, ExpPos, GetKeyFnName, ModelTriggerType, QueryCache, Template, bind, buildHTML, classes, computed, createRef, decorator, directive, event, forEach, html, ifElse, ifTrue, model, prop, query, queryAll, show, slot, state, styles, sync, tag, watch, when };
3172
+ export { CompElem, Decorator, DecoratorType, DecoratorWrapper, DecoratorsKey, Directive, DirectiveUpdateTag, DirectiveWrapper, EnterPoint, EnterPointType, ExpPos, GetKeyFnName, ModelTriggerType, QueryCache, Template, _getObservedAttrs, bind, buildHTML, classes, computed, createRef, decorator, directive, event, forEach, html, ifElse, ifTrue, makeProp, makeState, model, prop, query, queryAll, show, slot, state, styles, sync, tag, watch, when };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "compelem",
3
- "version": "0.1.1-beta",
3
+ "version": "0.2.1-beta",
4
4
  "description": "A modern, reactive, fast, lightweight and flexible lib for building web components",
5
5
  "main": "index.js",
6
6
  "module": "index.js",
package/utils.d.ts CHANGED
@@ -1,5 +1,7 @@
1
+ import { CompElem } from "./CompElem";
1
2
  export declare function showError(msg: string): void;
2
3
  export declare function showTagError(tagName: string, msg: string): void;
3
4
  export declare function showWarn(...args: unknown[]): void;
4
5
  export declare function showTagWarn(tagName: string, msg: string): void;
5
- export declare function toUpdatePath(varPath: string[]): string;
6
+ export declare function _toUpdatePath(varPath: string[]): string;
7
+ export declare function _getSuper(cls: CompElem): any;