From 65753a6e026b12e61bce29df3a7b87d7987121a4 Mon Sep 17 00:00:00 2001 From: yutent Date: Wed, 8 Mar 2023 11:11:05 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=80=E5=A4=A7=E6=B3=A2=E7=B2=BE=E7=AE=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- src/constants.js | 50 +++++++++++- src/html.js | 142 ++++---------------------------- src/index.js | 206 ++++++++++++----------------------------------- 4 files changed, 120 insertions(+), 280 deletions(-) diff --git a/package.json b/package.json index c98e79a..7fe0cac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ninejs/core", - "version": "0.1.0", + "version": "0.2.0", "type": "module", "description": "9号UI组件库的核心", "main": "dist/index.js", diff --git a/src/constants.js b/src/constants.js index 9652672..d784afd 100644 --- a/src/constants.js +++ b/src/constants.js @@ -4,9 +4,57 @@ * @date 2023/03/06 12:08:35 */ -export const finalize = Symbol('finalize') +export const FINALIZED = Symbol('finalized') +export const UPDATE = Symbol('update') export const RESET_CSS_STYLE = ` * {box-sizing: border-box;margin: 0;padding: 0;} ::before,::after {box-sizing: border-box;} ` + +export const DEFAULT_CONVERTER = { + toAttribute(value, type) { + switch (type) { + case Boolean: + value = value ? '' : null + break + case Object: + case Array: + value = value == null ? value : JSON.stringify(value) + break + } + return value + }, + fromAttribute(value, type) { + let fromValue = value + switch (type) { + case Boolean: + fromValue = value !== null + break + case Number: + fromValue = value === null ? null : Number(value) + break + case Object: + case Array: + try { + fromValue = JSON.parse(value) + } catch (e) { + fromValue = null + } + break + } + return fromValue + } +} + +export function notEqual(value, old) { + return old !== value && (old === old || value === value) +} + +export const DEFAULT_PROPERTY_DECLARATION = { + attribute: true, + type: String, + converter: DEFAULT_CONVERTER, + reflect: false, + hasChanged: notEqual +} diff --git a/src/html.js b/src/html.js index b251fcb..759e5af 100644 --- a/src/html.js +++ b/src/html.js @@ -1,11 +1,8 @@ var ENABLE_EXTRA_SECURITY_HOOKS = true var global3 = window -var debugLogEvent2 = void 0 var debugLogRenderId = 0 var issueWarning2 -var wrap = node => node - var identityFunction = value => value var noopSanitizer = (_node, _name, _type) => identityFunction var setSanitizer = newSanitizer => { @@ -262,15 +259,6 @@ class Template { } nodeIndex++ } - debugLogEvent2 === null || debugLogEvent2 === void 0 - ? void 0 - : debugLogEvent2({ - kind: 'template prep', - template: this, - clonableTemplate: this.el, - parts: this.parts, - strings - }) } static createElement(html2, _options) { const el = d.createElement('template') @@ -396,16 +384,6 @@ class TemplateInstance { let i = 0 for (const part of this._parts) { if (part !== void 0) { - debugLogEvent2 === null || debugLogEvent2 === void 0 - ? void 0 - : debugLogEvent2({ - kind: 'set part', - part, - value: values[i], - valueIndex: i, - values, - templateInstance: this - }) if (part.strings !== void 0) { part._$setValue(values, part, i) i += part.strings.length - 2 @@ -448,7 +426,7 @@ class ChildPart { : this.__isConnected } get parentNode() { - let parentNode = wrap(this._$startNode).parentNode + let parentNode = this._$startNode.parentNode const parent = this._$parent if (parent !== void 0 && parentNode.nodeType === 11) { parentNode = parent.parentNode @@ -468,15 +446,6 @@ class ChildPart { if (isPrimitive(value)) { if (value === nothing || value == null || value === '') { if (this._$committedValue !== nothing) { - debugLogEvent2 === null || debugLogEvent2 === void 0 - ? void 0 - : debugLogEvent2({ - kind: 'commit nothing to child', - start: this._$startNode, - end: this._$endNode, - parent: this._$parent, - options: this.options - }) this._$clear() } this._$committedValue = nothing @@ -494,7 +463,7 @@ class ChildPart { } } _insert(node, ref = this._$endNode) { - return wrap(wrap(this._$startNode).parentNode).insertBefore(node, ref) + return this._$startNode.parentNode.insertBefore(node, ref) } _commitNode(value) { var _a4 @@ -514,15 +483,7 @@ class ChildPart { throw new Error(message) } } - debugLogEvent2 === null || debugLogEvent2 === void 0 - ? void 0 - : debugLogEvent2({ - kind: 'commit node', - start: this._$startNode, - parent: this._$parent, - value, - options: this.options - }) + this._$committedValue = this._insert(value) } } @@ -531,21 +492,14 @@ class ChildPart { this._$committedValue !== nothing && isPrimitive(this._$committedValue) ) { - const node = wrap(this._$startNode).nextSibling + const node = this._$startNode.nextSibling if (ENABLE_EXTRA_SECURITY_HOOKS) { if (this._textSanitizer === void 0) { this._textSanitizer = createSanitizer(node, 'data', 'property') } value = this._textSanitizer(value) } - debugLogEvent2 === null || debugLogEvent2 === void 0 - ? void 0 - : debugLogEvent2({ - kind: 'commit text', - node, - value, - options: this.options - }) + node.data = value } else { if (ENABLE_EXTRA_SECURITY_HOOKS) { @@ -555,25 +509,10 @@ class ChildPart { this._textSanitizer = createSanitizer(textNode, 'data', 'property') } value = this._textSanitizer(value) - debugLogEvent2 === null || debugLogEvent2 === void 0 - ? void 0 - : debugLogEvent2({ - kind: 'commit text', - node: textNode, - value, - options: this.options - }) + textNode.data = value } else { this._commitNode(d.createTextNode(value)) - debugLogEvent2 === null || debugLogEvent2 === void 0 - ? void 0 - : debugLogEvent2({ - kind: 'commit text', - node: wrap(this._$startNode).nextSibling, - value, - options: this.options - }) } } this._$committedValue = value @@ -635,18 +574,18 @@ class ChildPart { partIndex++ } if (partIndex < itemParts.length) { - this._$clear(itemPart && wrap(itemPart._$endNode).nextSibling, partIndex) + this._$clear(itemPart && itemPart._$endNode.nextSibling, partIndex) itemParts.length = partIndex } } - _$clear(start = wrap(this._$startNode).nextSibling, from) { + _$clear(start = this._$startNode.nextSibling, from) { var _a4 ;(_a4 = this._$notifyConnectionChanged) === null || _a4 === void 0 ? void 0 : _a4.call(this, false, true, from) while (start && start !== this._$endNode) { - const n = wrap(start).nextSibling - wrap(start).remove() + const n = start.nextSibling + start.remove() start = n } } @@ -720,7 +659,7 @@ class AttributePart { } _commitValue(value) { if (value === nothing) { - wrap(this.element).removeAttribute(this.name) + this.element.removeAttribute(this.name) } else { if (ENABLE_EXTRA_SECURITY_HOOKS) { if (this._sanitizer === void 0) { @@ -732,16 +671,8 @@ class AttributePart { } value = this._sanitizer(value !== null && value !== void 0 ? value : '') } - debugLogEvent2 === null || debugLogEvent2 === void 0 - ? void 0 - : debugLogEvent2({ - kind: 'commit attribute', - element: this.element, - name: this.name, - value, - options: this.options - }) - wrap(this.element).setAttribute( + + this.element.setAttribute( this.name, value !== null && value !== void 0 ? value : '' ) @@ -764,15 +695,7 @@ class PropertyPart extends AttributePart { } value = this._sanitizer(value) } - debugLogEvent2 === null || debugLogEvent2 === void 0 - ? void 0 - : debugLogEvent2({ - kind: 'commit property', - element: this.element, - name: this.name, - value, - options: this.options - }) + this.element[this.name] = value === nothing ? void 0 : value } } @@ -783,22 +706,10 @@ class BooleanAttributePart extends AttributePart { this.type = BOOLEAN_ATTRIBUTE_PART } _commitValue(value) { - debugLogEvent2 === null || debugLogEvent2 === void 0 - ? void 0 - : debugLogEvent2({ - kind: 'commit boolean attribute', - element: this.element, - name: this.name, - value: !!(value && value !== nothing), - options: this.options - }) if (value && value !== nothing) { - wrap(this.element).setAttribute( - this.name, - emptyStringForBooleanAttribute2 - ) + this.element.setAttribute(this.name, emptyStringForBooleanAttribute2) } else { - wrap(this.element).removeAttribute(this.name) + this.element.removeAttribute(this.name) } } } @@ -826,18 +737,7 @@ class EventPart extends AttributePart { const shouldAddListener = newListener !== nothing && (oldListener === nothing || shouldRemoveListener) - debugLogEvent2 === null || debugLogEvent2 === void 0 - ? void 0 - : debugLogEvent2({ - kind: 'commit event listener', - element: this.element, - name: this.name, - value: newListener, - options: this.options, - removeListener: shouldRemoveListener, - addListener: shouldAddListener, - oldListener - }) + if (shouldRemoveListener) { this.element.removeEventListener(this.name, this, oldListener) } @@ -875,14 +775,6 @@ class ElementPart { return this._$parent._$isConnected } _$setValue(value) { - debugLogEvent2 === null || debugLogEvent2 === void 0 - ? void 0 - : debugLogEvent2({ - kind: 'commit to element binding', - element: this.element, - value, - options: this.options - }) resolveDirective(this, value) } } diff --git a/src/index.js b/src/index.js index c74427c..2f29c47 100644 --- a/src/index.js +++ b/src/index.js @@ -3,6 +3,13 @@ * @author yutent * @date 2023/03/07 18:10:43 */ +import { + FINALIZED, + UPDATE, + DEFAULT_CONVERTER, + DEFAULT_PROPERTY_DECLARATION, + notEqual +} from './constants.js' import { css, adoptStyles } from './css.js' import { render, html, svg } from './html.js' import { @@ -16,10 +23,9 @@ import { clearOutsideClick, fire } from './utils.js' + +export { html, css, svg } export { - html, - css, - svg, $, $$, nextTick, @@ -30,52 +36,6 @@ export { clearOutsideClick } -var defaultConverter = { - toAttribute(value, type) { - switch (type) { - case Boolean: - value = value ? '' : null - break - case Object: - case Array: - value = value == null ? value : JSON.stringify(value) - break - } - return value - }, - fromAttribute(value, type) { - let fromValue = value - switch (type) { - case Boolean: - fromValue = value !== null - break - case Number: - fromValue = value === null ? null : Number(value) - break - case Object: - case Array: - try { - fromValue = JSON.parse(value) - } catch (e) { - fromValue = null - } - break - } - return fromValue - } -} -var notEqual = (value, old) => { - return old !== value && (old === old || value === value) -} -var defaultPropertyDeclaration = { - attribute: true, - type: String, - converter: defaultConverter, - reflect: false, - hasChanged: notEqual -} -var finalized = 'finalized' - export class Component extends HTMLElement { constructor() { super() @@ -85,14 +45,14 @@ export class Component extends HTMLElement { this.hasUpdated = false this.__reflectingProperty = null this._initialize() + this.created && this.created() } static addInitializer(initializer) { - var _a4 this.finalize() - ;((_a4 = this._initializers) !== null && _a4 !== void 0 - ? _a4 - : (this._initializers = []) - ).push(initializer) + if (!this._initializers) { + this._initializers = [] + } + this._initializers.push(initializer) } static get observedAttributes() { this.finalize() @@ -106,11 +66,11 @@ export class Component extends HTMLElement { }) return attributes } - static createProperty(name, options = defaultPropertyDeclaration) { + static createProperty(name, options = DEFAULT_PROPERTY_DECLARATION) { if (options.state) { options.attribute = false } - this.finalize() + this.elementProperties.set(name, options) let key = Symbol(name) @@ -133,13 +93,13 @@ export class Component extends HTMLElement { } } static getPropertyOptions(name) { - return this.elementProperties.get(name) || defaultPropertyDeclaration + return this.elementProperties.get(name) || DEFAULT_PROPERTY_DECLARATION } static finalize() { - if (this.hasOwnProperty(finalized)) { + if (this[FINALIZED]) { return false } - this[finalized] = true + this[FINALIZED] = true this.elementProperties = new Map() this.__attributeToPropertyMap = new Map() @@ -163,32 +123,24 @@ export class Component extends HTMLElement { : void 0 } _initialize() { - var _a4 this.__updatePromise = new Promise(res => (this.enableUpdating = res)) this._$changedProperties = new Map() this.__saveInstanceProperties() this.requestUpdate() - ;(_a4 = this.constructor._initializers) === null || _a4 === void 0 - ? void 0 - : _a4.forEach(i => i(this)) + this.constructor._initializers?.forEach(i => i(this)) } addController(controller) { - var _a4, _b4 - ;((_a4 = this.__controllers) !== null && _a4 !== void 0 - ? _a4 - : (this.__controllers = []) - ).push(controller) + if (!this.__controllers) { + this.__controllers = [] + } + this.__controllers.push(controller) + if (this.root !== void 0 && this.isConnected) { - ;(_b4 = controller.hostConnected) === null || _b4 === void 0 - ? void 0 - : _b4.call(controller) + controller.hostConnected?.call(controller) } } removeController(controller) { - var _a4 - ;(_a4 = this.__controllers) === null || _a4 === void 0 - ? void 0 - : _a4.splice(this.__controllers.indexOf(controller) >>> 0, 1) + this.__controllers?.splice(this.__controllers.indexOf(controller) >>> 0, 1) } __saveInstanceProperties() { this.constructor.elementProperties.forEach((_v, p) => { @@ -198,54 +150,33 @@ export class Component extends HTMLElement { } }) } - createRenderRoot() { - let root = this.shadowRoot || this.attachShadow({ mode: 'open' }) - adoptStyles(root, this.constructor.styles) - return root - } + connectedCallback() { - var _a4 - if (this.root === void 0) { - this.root = this.createRenderRoot() - } + this.root = this.shadowRoot || this.attachShadow({ mode: 'open' }) + + adoptStyles(this.root, this.constructor.styles) this.enableUpdating(true) - ;(_a4 = this.__controllers) === null || _a4 === void 0 - ? void 0 - : _a4.forEach(c => { - var _a5 - return (_a5 = c.hostConnected) === null || _a5 === void 0 - ? void 0 - : _a5.call(c) - }) - this.__childPart && this.__childPart.setConnected(true) + + this.__controllers?.forEach(it => it.hostConnected?.call(it)) + this.__childPart?.setConnected(true) + + this.mounted && this.mounted() } enableUpdating(_requestedUpdate) {} disconnectedCallback() { - var _a4 - ;(_a4 = this.__controllers) === null || _a4 === void 0 - ? void 0 - : _a4.forEach(c => { - var _a5 - return (_a5 = c.hostDisconnected) === null || _a5 === void 0 - ? void 0 - : _a5.call(c) - }) - this.__childPart && this.__childPart.setConnected(false) + this.__controllers?.forEach(it => it.hostDisconnected?.call(it)) + this.__childPart?.setConnected(false) } attributeChangedCallback(name, _old, value) { this._$attributeToProperty(name, value) } - __propertyToAttribute(name, value, options = defaultPropertyDeclaration) { - var _a4 + __propertyToAttribute(name, value, options = DEFAULT_PROPERTY_DECLARATION) { const attr = this.constructor.__attributeNameForProperty(name, options) if (attr !== void 0 && options.reflect === true) { - const converter = - ((_a4 = options.converter) === null || _a4 === void 0 - ? void 0 - : _a4.toAttribute) !== void 0 - ? options.converter - : defaultConverter + const converter = options.converter?.toAttribute + ? options.converter + : DEFAULT_CONVERTER const attrValue = converter.toAttribute(value, options.type) this.__reflectingProperty = name @@ -258,7 +189,6 @@ export class Component extends HTMLElement { } } _$attributeToProperty(name, value) { - var _a4 const ctor = this.constructor const propName = ctor.__attributeToPropertyMap.get(name) if (propName !== void 0 && this.__reflectingProperty !== propName) { @@ -266,11 +196,9 @@ export class Component extends HTMLElement { const converter = typeof options.converter === 'function' ? { fromAttribute: options.converter } - : ((_a4 = options.converter) === null || _a4 === void 0 - ? void 0 - : _a4.fromAttribute) !== void 0 + : options.converter?.fromAttribute ? options.converter - : defaultConverter + : DEFAULT_CONVERTER this.__reflectingProperty = propName this[propName] = converter.fromAttribute(value, options.type) this.__reflectingProperty = null @@ -316,7 +244,6 @@ export class Component extends HTMLElement { return this.performUpdate() } performUpdate() { - var _a4, _b4 if (!this.isUpdatePending) { return } @@ -325,44 +252,20 @@ export class Component extends HTMLElement { this.__instanceProperties.forEach((v, p) => (this[p] = v)) this.__instanceProperties = void 0 } - let shouldUpdate = false + const changedProperties = this._$changedProperties try { - shouldUpdate = this.shouldUpdate(changedProperties) - if (shouldUpdate) { - this.willUpdate(changedProperties) - ;(_b4 = this.__controllers) === null || _b4 === void 0 - ? void 0 - : _b4.forEach(c => { - var _a5 - return (_a5 = c.hostUpdate) === null || _a5 === void 0 - ? void 0 - : _a5.call(c) - }) - this.update(changedProperties) - } else { - this.__markUpdated() - } + this.__controllers?.forEach(it => it.hostUpdate?.call(it)) + this[UPDATE](changedProperties) + this._$didUpdate(changedProperties) } catch (e) { - shouldUpdate = false this.__markUpdated() throw e } - if (shouldUpdate) { - this._$didUpdate(changedProperties) - } } - willUpdate(_changedProperties) {} _$didUpdate(changedProperties) { - var _a4 - ;(_a4 = this.__controllers) === null || _a4 === void 0 - ? void 0 - : _a4.forEach(c => { - var _a5 - return (_a5 = c.hostUpdated) === null || _a5 === void 0 - ? void 0 - : _a5.call(c) - }) + this.__controllers?.forEach(it => it.hostUpdated?.call(it)) + if (!this.hasUpdated) { this.hasUpdated = true this.firstUpdated(changedProperties) @@ -379,13 +282,10 @@ export class Component extends HTMLElement { getUpdateComplete() { return this.__updatePromise } - shouldUpdate(_changedProperties) { - return true - } - update(_changedProperties) { - const value = this.render() - /* */ + [UPDATE](_changedProperties) { + let value = this.render() + if (this.__reflectingProperties !== void 0) { this.__reflectingProperties.forEach((v, k) => this.__propertyToAttribute(k, this[k], v)