diff --git a/packages/core/src/main.ts b/packages/core/src/main.ts index 76d6de7..d3ae188 100644 --- a/packages/core/src/main.ts +++ b/packages/core/src/main.ts @@ -24,14 +24,12 @@ if(process.env.NODE_ENV === 'development') { console.info(`%cquarkc@${version}`, 'color: white;background:#9f57f8;font-weight:bold;font-size:10px;padding:2px 6px;border-radius: 5px','Running in dev mode.') } -type Falsy = false | 0 | '' | null | undefined - /** - * Check if val is empty. Falsy values except than 'false' and '0' are considered empty. + * Check if val is null or undefined. * - * 判断是否为空值,falsy值中'false'和'0'不算 + * 判断是否为空值, */ -const isEmpty = (val: unknown): val is Exclude => !(val || val === false || val === 0); +const isEmpty = (val: unknown): val is (null | undefined) => val == null; const defaultPropertyDeclaration: PropertyDeclaration = { observed: true, @@ -231,6 +229,7 @@ function getWrapperClass(target: typeof QuarkElement, style: string) { } const isBoolProp = type === Boolean; + const hasConverter = isFunction(converter); /** convert attribute's value to its decorated counterpart, that is, property's value */ const convertAttrValue = (value: string | null) => { // * For boolean properties, ignore the defaultValue specified. @@ -238,16 +237,15 @@ function getWrapperClass(target: typeof QuarkElement, style: string) { if ( !isBoolProp && isEmpty(value) - && !isEmpty(defaultValue) ) { return defaultValue; } - if (isFunction(converter)) { - return converter(value, type); + if (!hasConverter) { + return value; } - return value; + return converter(value, type); }; const dep = new Dep(); Props.set(this, attrName, { @@ -261,7 +259,7 @@ function getWrapperClass(target: typeof QuarkElement, style: string) { propName, { get(this: QuarkElement) { - dep.depend() + dep.depend(); return convertAttrValue(this.getAttribute(attrName)); }, set(this: QuarkElement, val: string | boolean | null) { @@ -491,23 +489,13 @@ export class QuarkElement extends HTMLElement implements ReactiveControllerHost this.rootPatch(newRootVNode); } - /** update properties by DOM attributes' changes */ + /** sync property with its attribute counterpart */ private _updateObservedProps() { (this.constructor as QuarkElementWrapper)._observedAttrs.forEach( - ([attrName, { + ([_, { propName, - options: { - type, - converter, - }, }]) => { - let val = this.getAttribute(attrName); - - if (isFunction(converter)) { - val = converter(val, type); - } - - this[propName] = val; + this[propName] = this[propName]; } ); } diff --git a/packages/core/test/comp.test.ts b/packages/core/test/comp.test.ts index 8b4975b..f445a9a 100644 --- a/packages/core/test/comp.test.ts +++ b/packages/core/test/comp.test.ts @@ -82,8 +82,8 @@ describe('@property', () => { const camelCaseNode = comp.shadowRoot?.querySelector('.test1-camelcase'); expect(node).to.exist; expect(camelCaseNode).to.exist; - expect(node!.textContent).to.equal('0'); - expect(camelCaseNode!.textContent).to.equal('camelcased'); + expect(node!.textContent).to.equal('lowercased'); + expect(camelCaseNode!.textContent, 'camelcased name share the same value with lowercased name').to.equal('lowercased'); comp!.setAttribute('testattr', '1'); await nextTick(); expect(node!.textContent).to.equal('1'); @@ -176,6 +176,16 @@ describe('@property', () => { await nextTick(); expect(node!.textContent).to.equal('welcome to japari park!'); }); + + it('not set, use default value', async () => { + const comp = await render(); + const node = comp.shadowRoot?.querySelector('.test8'); + expect(node).to.exist; + expect(node!.textContent).to.equal('18'); + comp!.setAttribute('testattr8', '1'); + await nextTick(); + expect(node!.textContent).to.equal('1'); + }); }); describe('Fragment', () => { diff --git a/packages/core/test/components/test-property.tsx b/packages/core/test/components/test-property.tsx index 66f3d07..dc46184 100644 --- a/packages/core/test/components/test-property.tsx +++ b/packages/core/test/components/test-property.tsx @@ -15,7 +15,7 @@ declare global { @customElement({ tag }) class TestProperty extends QuarkElement { @property() - testattr = '0'; + testattr = 'lowercased'; /** except for initial value, will work the same as testattr */ @property() @@ -44,6 +44,9 @@ class TestProperty extends QuarkElement { @property({ type: Boolean }) testattr7 = true; + @property({ type: Number }) + testattr8 = 18; + /** boolean property with its value default to true should be ignored */ @property({ type: Boolean, attribute: 'aria-hidden' }) testAriaHidden = false; @@ -60,6 +63,7 @@ class TestProperty extends QuarkElement {
{this.testattr6.join(' ')}
{this.testattr7.toString()}
{this.testAriaHidden.toString()}
+
{this.testattr8.toString()}
); }