parent
b4e7f5dfae
commit
ea6010c782
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "wkit",
|
||||
"version": "1.11.1",
|
||||
"version": "1.11.2",
|
||||
"type": "module",
|
||||
"description": "A library for building fast, lightweight web components.",
|
||||
"main": "dist/index.js",
|
||||
|
|
120
src/html.js
120
src/html.js
|
@ -143,16 +143,20 @@ function getTemplateHtml(strings, type) {
|
|||
}
|
||||
|
||||
class Template {
|
||||
parts = []
|
||||
|
||||
constructor({ strings, ['__dom_type__']: type }, options) {
|
||||
this.parts = []
|
||||
let node
|
||||
let nodeIndex = 0
|
||||
let attrNameIndex = 0
|
||||
let partCount = strings.length - 1
|
||||
let parts = this.parts
|
||||
let [html2, attrNames] = getTemplateHtml(strings, type)
|
||||
|
||||
this.el = Template.createElement(html2)
|
||||
|
||||
walker.currentNode = this.el.content
|
||||
|
||||
if (type === SVG_RESULT) {
|
||||
let content = this.el.content
|
||||
let svgElement = content.firstChild
|
||||
|
@ -327,6 +331,7 @@ class TemplateInstance {
|
|||
|
||||
return fragment
|
||||
}
|
||||
|
||||
update(values) {
|
||||
let i = 0
|
||||
for (let part of this.$parts) {
|
||||
|
@ -344,10 +349,10 @@ class TemplateInstance {
|
|||
}
|
||||
|
||||
class ChildPart {
|
||||
type = CHILD_PART
|
||||
#value = NOTHING
|
||||
|
||||
constructor(startNode, endNode, parent, options) {
|
||||
this.type = CHILD_PART
|
||||
this.startNode = startNode
|
||||
this.endNode = endNode
|
||||
this.$parent = parent
|
||||
|
@ -363,7 +368,7 @@ class ChildPart {
|
|||
return parentNode
|
||||
}
|
||||
|
||||
$setValue(value) {
|
||||
$setValue(value, clear) {
|
||||
if (isPrimitive(value)) {
|
||||
if (value === NOTHING || value == null || value === '') {
|
||||
if (this.#value !== NOTHING) {
|
||||
|
@ -382,16 +387,22 @@ class ChildPart {
|
|||
} else {
|
||||
this.#commitText(value)
|
||||
}
|
||||
if (clear) {
|
||||
nextTick(_ => this.#clearBindings())
|
||||
}
|
||||
}
|
||||
|
||||
#insert(node, target = this.endNode) {
|
||||
return this.startNode.parentNode.insertBefore(node, target)
|
||||
}
|
||||
|
||||
#commitNode(value) {
|
||||
if (this.#value !== value) {
|
||||
this.#clear()
|
||||
this.#value = this.#insert(value)
|
||||
}
|
||||
}
|
||||
|
||||
#commitText(value) {
|
||||
if (this.#value !== NOTHING && isPrimitive(this.#value)) {
|
||||
let node = this.startNode.nextSibling
|
||||
|
@ -402,6 +413,7 @@ class ChildPart {
|
|||
}
|
||||
this.#value = value
|
||||
}
|
||||
|
||||
#commitTemplateResult(result) {
|
||||
let { values, ['__dom_type__']: type } = result
|
||||
let template =
|
||||
|
@ -422,12 +434,14 @@ class ChildPart {
|
|||
this.#value = instance
|
||||
}
|
||||
}
|
||||
|
||||
#getTemplate(result) {
|
||||
let template = TEMPLATE_CACHE.get(result.strings.join())
|
||||
let key = result.strings.join()
|
||||
let template = TEMPLATE_CACHE.get(key)
|
||||
|
||||
if (template === void 0) {
|
||||
template = new Template(result, this.options)
|
||||
TEMPLATE_CACHE.set(result.strings.join(), template)
|
||||
TEMPLATE_CACHE.set(key, template)
|
||||
}
|
||||
return template
|
||||
}
|
||||
|
@ -469,14 +483,32 @@ class ChildPart {
|
|||
start = node
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除已被移除的节点事件
|
||||
*/
|
||||
#clearBindings() {
|
||||
let host = this.options.host
|
||||
let events = host.$events
|
||||
|
||||
for (let ev in events) {
|
||||
for (let i = -1, it; (it = events[ev][++i]); ) {
|
||||
if (!host.root.contains(it.el)) {
|
||||
it.el.removeEventListener(this.name, it.listener, it.options)
|
||||
events[ev][i] = null
|
||||
}
|
||||
}
|
||||
events[ev] = events[ev].filter(e => e !== null)
|
||||
}
|
||||
}
|
||||
}
|
||||
// 常规属性
|
||||
class AttributePart {
|
||||
type = ATTRIBUTE_PART
|
||||
|
||||
#value = NOTHING
|
||||
|
||||
constructor(element, name, strings, decorates, parent, options = {}) {
|
||||
this.type = ATTRIBUTE_PART
|
||||
|
||||
this.element = element
|
||||
this.name = name
|
||||
this.decorates = decorates
|
||||
|
@ -494,6 +526,7 @@ class AttributePart {
|
|||
$setValue(value, valueIndex) {
|
||||
let strings = this.strings
|
||||
let changed = false
|
||||
|
||||
if (strings === void 0) {
|
||||
changed = !isPrimitive(value) || value !== this.#value
|
||||
if (changed) {
|
||||
|
@ -521,26 +554,28 @@ class AttributePart {
|
|||
}
|
||||
|
||||
commitValue(value) {
|
||||
let isBoolAttr = boolMap[this.name]
|
||||
let elem = this.element
|
||||
let attr = this.name
|
||||
let isBoolAttr = boolMap[attr]
|
||||
// ref属性不渲染到节点上
|
||||
if (this.name === 'ref') {
|
||||
this.options.host.$refs[value] = this.element
|
||||
if (attr === 'ref') {
|
||||
this.options.host.$refs[value] = elem
|
||||
return
|
||||
}
|
||||
|
||||
if (isBoolAttr) {
|
||||
this.element[isBoolAttr] = !(value === false || value === null)
|
||||
elem[isBoolAttr] = !(value === false || value === null)
|
||||
|
||||
if (this.element[isBoolAttr]) {
|
||||
this.element.setAttribute(this.name, '')
|
||||
if (elem[isBoolAttr]) {
|
||||
elem.setAttribute(attr, '')
|
||||
} else {
|
||||
this.element.removeAttribute(this.name)
|
||||
elem.removeAttribute(attr)
|
||||
}
|
||||
} else {
|
||||
if (value === null || value === void 0) {
|
||||
this.element.removeAttribute(this.name)
|
||||
elem.removeAttribute(attr)
|
||||
} else {
|
||||
this.element.setAttribute(this.name, value)
|
||||
elem.setAttribute(attr, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -562,20 +597,23 @@ class AnimPart extends AttributePart {
|
|||
}
|
||||
|
||||
commitValue({ type = 'fade', duration, custom, immediate = false } = {}) {
|
||||
let elem = this.element
|
||||
let fromto = MODES[type] || MODES.fade
|
||||
|
||||
if (custom) {
|
||||
fromto = custom
|
||||
}
|
||||
this.element.$animate = function (out = false) {
|
||||
elem.$animate = function (out = false) {
|
||||
return animate.call(this, duration, fromto, out)
|
||||
}
|
||||
this.element.$animate.immediate = immediate
|
||||
elem.$animate.immediate = immediate
|
||||
}
|
||||
}
|
||||
|
||||
// 事件属性
|
||||
class EventPart extends AttributePart {
|
||||
type = EVENT_PART
|
||||
|
||||
#listener = null
|
||||
|
||||
#prevent = noop
|
||||
|
@ -584,30 +622,14 @@ class EventPart extends AttributePart {
|
|||
|
||||
constructor(...args) {
|
||||
super(...args)
|
||||
this.type = EVENT_PART
|
||||
}
|
||||
|
||||
#clearBindings() {
|
||||
let host = this.options.host
|
||||
let events = host.$events[this.name]
|
||||
|
||||
for (let i = -1, it; (it = events[++i]); ) {
|
||||
if (!host.root.contains(it.el)) {
|
||||
this.element.removeEventListener(this.name, it.listener, it.options)
|
||||
events[i] = null
|
||||
}
|
||||
}
|
||||
host.$events[this.name] = events.filter(it => it !== null)
|
||||
}
|
||||
|
||||
$setValue(listener) {
|
||||
let host = this.options.host
|
||||
let elem = this.element
|
||||
let name = this.name
|
||||
let options = {}
|
||||
let events = host.$events[this.name]
|
||||
|
||||
if (!events) {
|
||||
events = host.$events[this.name] = []
|
||||
}
|
||||
let events = host.$events[name] || []
|
||||
|
||||
if (this.decorates.length) {
|
||||
for (let it of this.decorates) {
|
||||
|
@ -619,7 +641,7 @@ class EventPart extends AttributePart {
|
|||
this.#prevent = ev => ev.preventDefault()
|
||||
break
|
||||
case 'self':
|
||||
this.#checkSelf = ev => ev.target === this.element
|
||||
this.#checkSelf = ev => ev.target === elem
|
||||
break
|
||||
case 'capture':
|
||||
case 'once':
|
||||
|
@ -634,14 +656,14 @@ class EventPart extends AttributePart {
|
|||
|
||||
if (this.#listener) {
|
||||
for (let i = -1, it; (it = events[++i]); ) {
|
||||
if (it.el === this.element) {
|
||||
if (it.el === elem) {
|
||||
shouldRemove =
|
||||
shouldRemove ||
|
||||
options.capture !== it.capture ||
|
||||
options.once !== it.once ||
|
||||
options.passive !== it.passive
|
||||
if (shouldRemove) {
|
||||
this.element.removeEventListener(this.name, it.listener, it.options)
|
||||
it.el.removeEventListener(name, it.listener, it.options)
|
||||
events[i] = null
|
||||
}
|
||||
break
|
||||
|
@ -650,20 +672,14 @@ class EventPart extends AttributePart {
|
|||
}
|
||||
|
||||
events = events.filter(it => it !== null)
|
||||
host.$events[this.name] = events
|
||||
host.$events[name] = events
|
||||
|
||||
if (listener && shouldRemove) {
|
||||
this.element.addEventListener(this.name, this, options)
|
||||
elem.addEventListener(name, this, options)
|
||||
this.#listener = listener
|
||||
|
||||
events.push({
|
||||
el: this.element,
|
||||
listener: this,
|
||||
options
|
||||
})
|
||||
events.push({ el: elem, listener: this, options })
|
||||
}
|
||||
|
||||
nextTick(_ => this.#clearBindings())
|
||||
}
|
||||
|
||||
handleEvent(ev) {
|
||||
|
@ -677,14 +693,14 @@ class EventPart extends AttributePart {
|
|||
}
|
||||
|
||||
class ElementPart {
|
||||
type = ELEMENT_PART
|
||||
constructor(element, parent, options) {
|
||||
this.element = element
|
||||
this.type = ELEMENT_PART
|
||||
this.$parent = parent
|
||||
this.options = options
|
||||
}
|
||||
|
||||
$setValue(value) {}
|
||||
$setValue() {}
|
||||
}
|
||||
|
||||
export function render(value, container, options = {}) {
|
||||
|
@ -699,7 +715,7 @@ export function render(value, container, options = {}) {
|
|||
)
|
||||
container[WC_PART] = part
|
||||
}
|
||||
part.$setValue(value)
|
||||
part.$setValue(value, true)
|
||||
|
||||
return part
|
||||
}
|
||||
|
|
|
@ -223,9 +223,6 @@ export class Component extends HTMLElement {
|
|||
return value
|
||||
},
|
||||
set: (target, prop, value, receiver) => {
|
||||
if (prop === 'length' && options.type === Array) {
|
||||
return true
|
||||
}
|
||||
let oldValue = target[prop]
|
||||
Reflect.set(target, prop, value, receiver)
|
||||
|
||||
|
|
Loading…
Reference in New Issue