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() {
|
||||
super()
|
||||
|
||||
// initialize dom tree and append to shadow root
|
||||
// initialize dom tree and append to shadow root, as well as initialize state
|
||||
this._initialize()
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,14 @@ export default (options: ComponentOptions) => {
|
|||
}
|
||||
}
|
||||
// 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])
|
||||
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>) {
|
||||
requestAnimationFrame(() => {
|
||||
|
@ -1025,4 +993,4 @@ export default (options: ComponentOptions) => {
|
|||
}
|
||||
|
||||
customElements.define(tag, CustomElementImpl)
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
import { parseTemplate } from './parseTemplate'
|
||||
import { processTemplateMacros } from './processTemplateMarco'
|
||||
import parseTemplate from './parseTemplate'
|
||||
import processTemplateMacros from './processTemplateMarco'
|
||||
import triggerDomUpdates from './triggerDomUpdates'
|
||||
|
||||
export default {
|
||||
parseTemplate,
|
||||
processTemplateMacros,
|
||||
triggerDomUpdates,
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export function parseTemplate(template: string): Element {
|
||||
export default function parseTemplate(template: string): Element {
|
||||
const parser = new DOMParser()
|
||||
const doc = parser.parseFromString(template, 'text/html')
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export function processTemplateMacros(
|
||||
export default function processTemplateMacros(
|
||||
element: Element,
|
||||
context: CustomElement,
|
||||
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