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