parent
5326af856c
commit
c9b21cd790
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@bd/core",
|
||||
"version": "1.8.8",
|
||||
"version": "1.9.0",
|
||||
"type": "module",
|
||||
"description": "百搭UI组件库的核心",
|
||||
"main": "dist/index.js",
|
||||
|
|
|
@ -36,7 +36,6 @@ const boolMap = Object.create(null)
|
|||
export { boolMap }
|
||||
|
||||
export const WC_PART = Symbol('wc_path')
|
||||
export const NO_CHANGE = Symbol('wc-noChange')
|
||||
export const NOTHING = Symbol('wc-nothing')
|
||||
export const __finalized__ = Symbol('finalized')
|
||||
export const __props__ = Symbol('props')
|
||||
|
|
182
src/html.js
182
src/html.js
|
@ -1,4 +1,4 @@
|
|||
import { boolMap, WC_PART, NO_CHANGE, NOTHING } from './constants.js'
|
||||
import { boolMap, WC_PART, NOTHING } from './constants.js'
|
||||
import { animate, MODES } from './anim.js'
|
||||
|
||||
const boundAttributeSuffix = '$wc$'
|
||||
|
@ -45,6 +45,8 @@ const COMMENT_PART = 7
|
|||
const templateCache = new WeakMap()
|
||||
const walker = document.createTreeWalker(document, 129, null, false)
|
||||
|
||||
function noop() {}
|
||||
|
||||
function getTemplateHtml(strings, type) {
|
||||
let len = strings.length - 1
|
||||
let attrNames = []
|
||||
|
@ -170,12 +172,19 @@ class Template {
|
|||
)
|
||||
let statics = value.split(marker)
|
||||
let m = /([#:@])?(.*)/.exec(realName)
|
||||
let decorates = []
|
||||
|
||||
if (m[1] === '@' && m[2].includes('.')) {
|
||||
decorates = m[2].split('.')
|
||||
m[2] = decorates.shift()
|
||||
}
|
||||
|
||||
parts.push({
|
||||
type: ATTRIBUTE_PART,
|
||||
index: nodeIndex,
|
||||
name: m[2],
|
||||
strings: statics,
|
||||
decorates,
|
||||
ctor:
|
||||
m[1] === ':'
|
||||
? PropertyPart
|
||||
|
@ -231,50 +240,6 @@ class Template {
|
|||
return el
|
||||
}
|
||||
}
|
||||
function resolveDirective(part, value, parent = part, attributeIndex) {
|
||||
if (value === NO_CHANGE) {
|
||||
return value
|
||||
}
|
||||
let currentDirective =
|
||||
attributeIndex !== void 0
|
||||
? parent.__directives?.[attributeIndex]
|
||||
: parent.__directive
|
||||
|
||||
let nextDirectiveConstructor = isPrimitive(value)
|
||||
? void 0
|
||||
: value['_$litDirective$']
|
||||
|
||||
if (currentDirective?.constructor !== nextDirectiveConstructor) {
|
||||
currentDirective._$notifyDirectiveConnectionChanged?.call(
|
||||
currentDirective,
|
||||
false
|
||||
)
|
||||
|
||||
if (nextDirectiveConstructor === void 0) {
|
||||
currentDirective = void 0
|
||||
} else {
|
||||
currentDirective = new nextDirectiveConstructor(part)
|
||||
currentDirective._$initialize(part, parent, attributeIndex)
|
||||
}
|
||||
if (attributeIndex !== void 0) {
|
||||
if (!parent.__directives) {
|
||||
parent.__directives = []
|
||||
}
|
||||
parent.__directives[attributeIndex] = currentDirective
|
||||
} else {
|
||||
parent.__directive = currentDirective
|
||||
}
|
||||
}
|
||||
if (currentDirective !== void 0) {
|
||||
value = resolveDirective(
|
||||
part,
|
||||
currentDirective._$resolve(part, value.values),
|
||||
currentDirective,
|
||||
attributeIndex
|
||||
)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
class TemplateInstance {
|
||||
constructor(template, parent) {
|
||||
|
@ -334,6 +299,7 @@ class TemplateInstance {
|
|||
node,
|
||||
templatePart.name,
|
||||
templatePart.strings,
|
||||
templatePart.decorates,
|
||||
this,
|
||||
options
|
||||
)
|
||||
|
@ -364,7 +330,7 @@ class TemplateInstance {
|
|||
for (let part of this._parts) {
|
||||
if (part !== void 0) {
|
||||
if (part.strings !== void 0) {
|
||||
part._$setValue(values, part, i)
|
||||
part._$setValue(values, i)
|
||||
i += part.strings.length - 2
|
||||
} else {
|
||||
part._$setValue(values[i])
|
||||
|
@ -403,15 +369,14 @@ class ChildPart {
|
|||
get endNode() {
|
||||
return this._$endNode
|
||||
}
|
||||
_$setValue(value, directiveParent = this) {
|
||||
value = resolveDirective(this, value, directiveParent)
|
||||
_$setValue(value) {
|
||||
if (isPrimitive(value)) {
|
||||
if (value === NOTHING || value == null || value === '') {
|
||||
if (this._$committedValue !== NOTHING) {
|
||||
this.#clear()
|
||||
}
|
||||
this._$committedValue = NOTHING
|
||||
} else if (value !== this._$committedValue && value !== NO_CHANGE) {
|
||||
} else if (value !== this._$committedValue) {
|
||||
this._commitText(value)
|
||||
}
|
||||
} else if (value['__dom_type__'] !== void 0) {
|
||||
|
@ -522,12 +487,13 @@ class ChildPart {
|
|||
}
|
||||
// 常规属性
|
||||
class AttributePart {
|
||||
constructor(element, name, strings, parent, options = {}) {
|
||||
constructor(element, name, strings, decorates, parent, options = {}) {
|
||||
this.type = ATTRIBUTE_PART
|
||||
this._$committedValue = NOTHING
|
||||
this._$disconnectableChildren = void 0
|
||||
this.element = element
|
||||
this.name = name
|
||||
this.decorates = decorates
|
||||
this._$parent = parent
|
||||
this.options = options
|
||||
if (strings.length > 2 || strings[0] !== '' || strings[1] !== '') {
|
||||
|
@ -544,15 +510,12 @@ class AttributePart {
|
|||
return this._$parent._$isConnected
|
||||
}
|
||||
|
||||
_$setValue(value, directiveParent = this, valueIndex, noCommit) {
|
||||
_$setValue(value, valueIndex) {
|
||||
let strings = this.strings
|
||||
let change = false
|
||||
let changed = false
|
||||
if (strings === void 0) {
|
||||
value = resolveDirective(this, value, directiveParent, 0)
|
||||
change =
|
||||
!isPrimitive(value) ||
|
||||
(value !== this._$committedValue && value !== NO_CHANGE)
|
||||
if (change) {
|
||||
changed = !isPrimitive(value) || value !== this._$committedValue
|
||||
if (changed) {
|
||||
this._$committedValue = value
|
||||
}
|
||||
} else {
|
||||
|
@ -560,16 +523,9 @@ class AttributePart {
|
|||
value = strings[0]
|
||||
|
||||
for (let i = 0; i < strings.length - 1; i++) {
|
||||
let v = resolveDirective(
|
||||
this,
|
||||
values[valueIndex + i],
|
||||
directiveParent,
|
||||
i
|
||||
)
|
||||
if (v === NO_CHANGE) {
|
||||
v = this._$committedValue[i]
|
||||
}
|
||||
change || (change = !isPrimitive(v) || v !== this._$committedValue[i])
|
||||
let v = values[valueIndex + i]
|
||||
|
||||
changed || (changed = !isPrimitive(v) || v !== this._$committedValue[i])
|
||||
if (v === NOTHING) {
|
||||
value = NOTHING
|
||||
} else if (value !== NOTHING) {
|
||||
|
@ -578,7 +534,7 @@ class AttributePart {
|
|||
this._$committedValue[i] = v
|
||||
}
|
||||
}
|
||||
if (change && !noCommit) {
|
||||
if (changed) {
|
||||
this.commitValue(value)
|
||||
}
|
||||
}
|
||||
|
@ -638,57 +594,87 @@ class AnimPart extends AttributePart {
|
|||
|
||||
// 事件属性
|
||||
class EventPart extends AttributePart {
|
||||
#listener = null
|
||||
|
||||
#prevent = noop
|
||||
#stop = noop
|
||||
#checkSelf = noop
|
||||
|
||||
constructor(...args) {
|
||||
super(...args)
|
||||
this.type = EVENT_PART
|
||||
}
|
||||
_$setValue(newListener, directiveParent = this) {
|
||||
newListener =
|
||||
resolveDirective(this, newListener, directiveParent, 0) || NOTHING
|
||||
|
||||
if (newListener === NO_CHANGE) {
|
||||
return
|
||||
}
|
||||
_$setValue(listener) {
|
||||
let host = this.options.host
|
||||
let oldListener = this._$committedValue
|
||||
let shouldRemoveListener =
|
||||
(newListener === NOTHING && oldListener !== NOTHING) ||
|
||||
newListener.capture !== oldListener.capture ||
|
||||
newListener.once !== oldListener.once ||
|
||||
newListener.passive !== oldListener.passive
|
||||
let shouldAddListener =
|
||||
newListener !== NOTHING &&
|
||||
(oldListener === NOTHING || shouldRemoveListener)
|
||||
let options = {}
|
||||
|
||||
if (shouldRemoveListener) {
|
||||
this.element.removeEventListener(this.name, this, oldListener)
|
||||
if (this.decorates.length) {
|
||||
for (let it of this.decorates) {
|
||||
switch (it) {
|
||||
case 'stop':
|
||||
this.#stop = ev => ev.stopPropagation()
|
||||
break
|
||||
case 'prevent':
|
||||
this.#prevent = ev => ev.preventDefault()
|
||||
break
|
||||
case 'self':
|
||||
this.#checkSelf = ev => ev.target === this.element
|
||||
break
|
||||
case 'capture':
|
||||
case 'once':
|
||||
case 'passive':
|
||||
options[it] = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (shouldAddListener) {
|
||||
this.element.addEventListener(this.name, this, newListener)
|
||||
|
||||
let shouldRemove = listener !== this.#listener
|
||||
|
||||
if (this.#listener && host.$events[this.name]) {
|
||||
for (let it of host.$events[this.name]) {
|
||||
if (it.el === this.element) {
|
||||
shouldRemove =
|
||||
options.capture !== it.capture ||
|
||||
options.once !== it.once ||
|
||||
options.passive !== it.passive
|
||||
if (shouldRemove) {
|
||||
this.element.removeEventListener(this.name, it.listener, it.options)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
this._$committedValue = newListener
|
||||
if (host) {
|
||||
|
||||
if (listener && shouldRemove) {
|
||||
this.element.addEventListener(this.name, this, options)
|
||||
this.#listener = listener
|
||||
|
||||
if (host.$events[this.name]) {
|
||||
host.$events[this.name].push({
|
||||
el: this.element,
|
||||
listener: this
|
||||
listener: this,
|
||||
options
|
||||
})
|
||||
} else {
|
||||
host.$events[this.name] = [
|
||||
{
|
||||
el: this.element,
|
||||
listener: this
|
||||
listener: this,
|
||||
options
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
handleEvent(event) {
|
||||
if (typeof this._$committedValue === 'function') {
|
||||
this._$committedValue.call(this.options.host || this.element, event)
|
||||
} else {
|
||||
this._$committedValue.handleEvent(event)
|
||||
handleEvent(ev) {
|
||||
this.#stop(ev)
|
||||
this.#prevent(ev)
|
||||
if (this.#checkSelf(ev) === false) {
|
||||
return
|
||||
}
|
||||
this.#listener.call(this.options.host, ev)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -703,9 +689,7 @@ class ElementPart {
|
|||
get _$isConnected() {
|
||||
return this._$parent._$isConnected
|
||||
}
|
||||
_$setValue(value) {
|
||||
resolveDirective(this, value)
|
||||
}
|
||||
_$setValue(value) {}
|
||||
}
|
||||
|
||||
export function render(value, container, options = {}) {
|
||||
|
|
Loading…
Reference in New Issue