feat: add triggerDomUpdates utility and refactor DOM update logic in main component
This commit is contained in:
parent
df92e93e7c
commit
4aed034100
52
src/main.ts
52
src/main.ts
|
@ -59,7 +59,7 @@ export default (options: ComponentOptions) => {
|
||||||
constructor() {
|
constructor() {
|
||||||
super()
|
super()
|
||||||
|
|
||||||
// initialize dom tree and append to shadow root
|
// initialize dom tree and append to shadow root, as well as initialize state
|
||||||
this._initialize()
|
this._initialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,14 @@ export default (options: ComponentOptions) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// trigger dom updates
|
// trigger dom updates
|
||||||
this._triggerDomUpdates(keyPath)
|
utils.triggerDomUpdates(keyPath, {
|
||||||
|
stateToElementsMap: this._stateToElementsMap,
|
||||||
|
textBindings: this._textBindings,
|
||||||
|
attributeBindings: this._attributeBindings,
|
||||||
|
updateTextNode: this._updateTextNode.bind(this),
|
||||||
|
getNestedState: this._getNestedState.bind(this),
|
||||||
|
scheduleUpdate: this._scheduleUpdate.bind(this),
|
||||||
|
})
|
||||||
if (this._statesListeners[keyPath])
|
if (this._statesListeners[keyPath])
|
||||||
this._statesListeners[keyPath](value)
|
this._statesListeners[keyPath](value)
|
||||||
|
|
||||||
|
@ -160,45 +167,6 @@ export default (options: ComponentOptions) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private _triggerDomUpdates(keyPath: string) {
|
|
||||||
if (this._stateToElementsMap[keyPath]) {
|
|
||||||
const updateQueue = new Set<HTMLElement>()
|
|
||||||
|
|
||||||
for (const element of this._stateToElementsMap[keyPath]) {
|
|
||||||
updateQueue.add(element)
|
|
||||||
}
|
|
||||||
|
|
||||||
this._scheduleUpdate(updateQueue)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update text bindings that depend on this state
|
|
||||||
if (this._textBindings) {
|
|
||||||
// this._textBindings.forEach((binding) => {
|
|
||||||
for (const binding of this._textBindings)
|
|
||||||
if (
|
|
||||||
binding.expr === keyPath ||
|
|
||||||
binding.expr.startsWith(`${keyPath}.`)
|
|
||||||
)
|
|
||||||
this._updateTextNode(
|
|
||||||
binding.node,
|
|
||||||
binding.expr,
|
|
||||||
binding.originalContent,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update attribute bindings that depend on this state
|
|
||||||
if (this._attributeBindings) {
|
|
||||||
for (const binding of this._attributeBindings)
|
|
||||||
if (
|
|
||||||
binding.expr === keyPath ||
|
|
||||||
binding.expr.startsWith(`${keyPath}.`)
|
|
||||||
) {
|
|
||||||
const value = this._getNestedState(binding.expr)
|
|
||||||
if (value !== undefined)
|
|
||||||
binding.element.setAttribute(binding.attrName, String(value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private _scheduleUpdate(elements: Set<HTMLElement>) {
|
private _scheduleUpdate(elements: Set<HTMLElement>) {
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
|
@ -1025,4 +993,4 @@ export default (options: ComponentOptions) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define(tag, CustomElementImpl)
|
customElements.define(tag, CustomElementImpl)
|
||||||
}
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
import { parseTemplate } from './parseTemplate'
|
import parseTemplate from './parseTemplate'
|
||||||
import { processTemplateMacros } from './processTemplateMarco'
|
import processTemplateMacros from './processTemplateMarco'
|
||||||
|
import triggerDomUpdates from './triggerDomUpdates'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
parseTemplate,
|
parseTemplate,
|
||||||
processTemplateMacros,
|
processTemplateMacros,
|
||||||
|
triggerDomUpdates,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export function parseTemplate(template: string): Element {
|
export default function parseTemplate(template: string): Element {
|
||||||
const parser = new DOMParser()
|
const parser = new DOMParser()
|
||||||
const doc = parser.parseFromString(template, 'text/html')
|
const doc = parser.parseFromString(template, 'text/html')
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export function processTemplateMacros(
|
export default function processTemplateMacros(
|
||||||
element: Element,
|
element: Element,
|
||||||
context: CustomElement,
|
context: CustomElement,
|
||||||
options: {
|
options: {
|
||||||
|
|
54
src/utils/triggerDomUpdates.ts
Normal file
54
src/utils/triggerDomUpdates.ts
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
export default function triggerDomUpdates(keyPath: string, ops: {
|
||||||
|
stateToElementsMap: Record<string, Set<HTMLElement>>,
|
||||||
|
scheduleUpdate: (elements: Set<HTMLElement>) => void,
|
||||||
|
textBindings: Array<{
|
||||||
|
node: Text
|
||||||
|
expr: string
|
||||||
|
originalContent: string
|
||||||
|
}> | undefined,
|
||||||
|
attributeBindings: Array<{
|
||||||
|
element: Element
|
||||||
|
attrName: string
|
||||||
|
expr: string
|
||||||
|
template: string
|
||||||
|
}> | undefined,
|
||||||
|
updateTextNode: (node: Text, expr: string, template: string) => void,
|
||||||
|
getNestedState: (path: string) => unknown,
|
||||||
|
}) {
|
||||||
|
if (ops.stateToElementsMap[keyPath]) {
|
||||||
|
const updateQueue = new Set<HTMLElement>()
|
||||||
|
|
||||||
|
for (const element of ops.stateToElementsMap[keyPath])
|
||||||
|
updateQueue.add(element)
|
||||||
|
|
||||||
|
ops.scheduleUpdate(updateQueue)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update text bindings that depend on this state
|
||||||
|
if (ops.textBindings) {
|
||||||
|
// this._textBindings.forEach((binding) => {
|
||||||
|
for (const binding of ops.textBindings)
|
||||||
|
if (
|
||||||
|
binding.expr === keyPath ||
|
||||||
|
binding.expr.startsWith(`${keyPath}.`)
|
||||||
|
)
|
||||||
|
ops.updateTextNode(
|
||||||
|
binding.node,
|
||||||
|
binding.expr,
|
||||||
|
binding.originalContent,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update attribute bindings that depend on this state
|
||||||
|
if (ops.attributeBindings) {
|
||||||
|
for (const binding of ops.attributeBindings)
|
||||||
|
if (
|
||||||
|
binding.expr === keyPath ||
|
||||||
|
binding.expr.startsWith(`${keyPath}.`)
|
||||||
|
) {
|
||||||
|
const value = ops.getNestedState(binding.expr)
|
||||||
|
if (value !== undefined)
|
||||||
|
binding.element.setAttribute(binding.attrName, String(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user