1
0
mirror of https://github.com/jaandrle/deka-dom-el synced 2025-07-29 07:00:16 +02:00
This commit is contained in:
2025-03-13 15:20:48 +01:00
parent 0a2d17ac6f
commit 8756dabc55
14 changed files with 266 additions and 154 deletions

View File

@@ -25,19 +25,32 @@ export function page({ pkg, info }){
el(h3, t`Debugging signals`),
el("p").append(T`
Signals are reactive primitives that update the UI when their values change. When debugging signals,
you need to track their values, understand their dependencies, and identify why updates are or aren't happening.
you need to track their values, understand their dependencies, and identify why updates are or arent
happening.
`),
el("h4", t`Inspecting signal values`),
el("p").append(T`
The simplest way to debug a signal is to log its current value by calling the get method:
The simplest way to debug a signal is to log its current value by calling the get or valueOf method:
`),
el(code, { content: `
const signal = S(0);
console.log('Current value:', signal.get());
// without triggering updates
console.log('Current value:', signal.valueOf());
`, page_id }),
el("div", { className: "warning" }).append(
el("p").append(T`
${el("code", "signal.get")} is OK, but in some situations may lead to unexpected results:
`),
el(code, { content: `
const signal = S(0);
const derived = S(()=> {
console.log('Current value:', signal.get());
// ↑ in rare cases this will register unwanted dependency
// but typically this is fine ↓
return signal.get() + 1;
});
` })
),
el("p").append(T`
You can also monitor signal changes by adding a listener:
`),
@@ -58,83 +71,7 @@ export function page({ pkg, info }){
),
el(example, { src: fileURL("./components/examples/debugging/consoleLog.js"), page_id }),
el(h3, t`Common signal debugging issues`),
el("h4", t`Signal updates not triggering UI changes`),
el("p", t`If signal updates arent reflected in the UI, check:`),
el("ul").append(
el("li", t`That youre using signal.set() to update the value, not modifying objects/arrays directly`),
el("li", t`For mutable objects, ensure youre using actions or making proper copies before updating`),
el("li", t`That the signal is actually connected to the DOM element (check your S.el or attribute binding code)`)
),
el(code, { src: fileURL("./components/examples/debugging/mutations.js"), page_id }),
el("h4", t`Memory leaks with signal listeners`),
el("p").append(T`
Signal listeners can cause memory leaks if not properly cleaned up. Always use AbortSignal
to cancel listeners.
`),
el("h4", t`Performance issues with frequently updating signals`),
el("p", t`If you notice performance issues with signals that update very frequently:`),
el("ul").append(
el("li", t`Consider debouncing or throttling signal updates`),
el("li", t`Make sure derived signals dont perform expensive calculations unnecessarily`),
el("li", t`Keep signal computations focused and minimal`)
),
el(code, { src: fileURL("./components/examples/debugging/debouncing.js"), page_id }),
el(h3, t`Browser DevTools tips for dd<el>`),
el("p").append(T`
When debugging in the browser, dd<el> provides several helpful DevTools-friendly features:
`),
el("h4", t`Identifying components in the DOM`),
el("p").append(T`
dd<el> marks components in the DOM with special comment nodes to help you identify component boundaries.
Components created with ${el("code", "el(ComponentFunction)")} are marked with comment nodes
${el("code", `<!--<dde:mark type="component" name="MyComponent" host="parentElement"/>-->`)} and
includes:
`),
el("ul").append(
el("li", t`type - Identifies the type of marker ("component", "reactive", or "later")`),
el("li", t`name - The name of the component function`),
el("li", t`host - Indicates whether the host is "this" (for DocumentFragments) or "parentElement"`),
),
el("h4", t`Finding reactive elements in the DOM`),
el("p").append(T`
When using ${el("code", "S.el()")}, dd<el> creates reactive elements in the DOM
that are automatically updated when signal values change. These elements are wrapped in special
comment nodes for debugging (to be true they are also used internally, so please do not edit them by hand):
`),
el(code, { src: fileURL("./components/examples/debugging/dom-reactive-mark.html"), page_id }),
el("p").append(T`
This is particularly useful when debugging why a reactive section isnt updating as expected.
You can inspect the elements between the comment nodes to see their current state and the
signal connections through \`__dde_reactive\` of the host element.
`),
el("h4", t`DOM inspection properties`),
el("p").append(T`
Elements created with the dd<el> library have special properties to aid in debugging:
`),
el("p").append(T`
${el("code", "<element>.__dde_reactive")} - An array property on DOM elements that tracks signal-to-element
relationships. This allows you to quickly identify which elements are reactive and what signals theyre
bound to. Each entry in the array contains:
`),
el("ul").append(
el("li", t`A pair of signal and listener function: [signal, listener]`),
el("li", t`Additional context information about the element or attribute`),
el("li", t`Automatically managed by signal.el(), signal.observedAttributes(), and processReactiveAttribute()`)
),
el("p").append(T`
These properties make it easier to understand the reactive structure of your application when inspecting
elements.
`),
el(example, { src: fileURL("./components/examples/signals/debugging-dom.js"), page_id }),
el("h4", t`Examining signal connections`),
el("h4", t`Examining signal via DevTools`),
el("p").append(T`
${el("code", "<signal>.__dde_signal")} - A Symbol property used to identify and store the internal state of
signal objects. It contains the following information:
@@ -148,22 +85,8 @@ export function page({ pkg, info }){
el("li", t`readonly: Boolean flag indicating if the signal is read-only`)
),
el("p").append(T`
…to determine the current value of the signal, call ${el("code", "signal.valueOf()")}.
`),
el("p").append(T`
You can inspect (host) element relationships and bindings with signals in the DevTools console using
${el("code", "$0.__dde_reactive")} (for currently selected element). In the console you will see a list of
${el("code", `[ [ signal, listener ], element, property ]`)}, where:
`),
el("ul").append(
el("li", t`signal — the signal triggering the changes`),
el("li", t`listener — the listener function (this is an internal function for dd<el>)`),
el("li", t`element — the DOM element that is bound to the signal`),
el("li", t`property — the attribute or property name which is changing based on the signal`),
),
el("p").append(T`
…the structure of \`__dde_reactive\` utilizes the browsers behavior of packing the first field,
so you can see the element and property that changes in the console right away.
…to determine the current value of the signal, call ${el("code", "signal.valueOf()")}. Dont hesitate to
use the debugger to inspect the signal object.
`),
el("h4", t`Debugging with breakpoints`),
@@ -185,5 +108,110 @@ export function page({ pkg, info }){
`)
),
el(h3, t`Common signal debugging issues`),
el("h4", t`Signal updates not triggering UI changes`),
el("p", t`If signal updates arent reflected in the UI, check:`),
el("ul").append(
el("li", t`That youre using signal.set() to update the value, not modifying objects/arrays directly`),
el("li", t`For mutable objects, ensure youre using actions or making proper copies before updating`),
el("li", t`That the signal is actually connected to the DOM element (check your S.el or attribute binding code)`)
),
el(code, { src: fileURL("./components/examples/debugging/mutations.js"), page_id }),
el("h4", t`Memory leaks with signal listeners`),
el("p").append(T`
Signal listeners can cause memory leaks if not properly cleaned up. Always use AbortSignal
to cancel listeners when they are used ouside the dd<el> knowledge (el, assign, S.el, … auto cleanup
unnecessarily signals automatically).
`),
el("h4", t`Performance issues with frequently updating signals`),
el("p", t`If you notice performance issues with signals that update very frequently:`),
el("ul").append(
el("li", t`Consider debouncing or throttling signal updates`),
el("li", t`Make sure derived signals dont perform expensive calculations unnecessarily`),
el("li", t`Keep signal computations focused and minimal`)
),
el(code, { src: fileURL("./components/examples/debugging/debouncing.js"), page_id }),
el(h3, t`Browser DevTools tips for components and reactivity`),
el("p").append(T`
When debugging in the browser, dd<el> provides several helpful DevTools-friendly features:
`),
el("h4", t`Finding reactive elements in the DOM`),
el("p").append(T`
When using ${el("code", "S.el()")}, dd<el> creates reactive elements in the DOM
that are automatically updated when signal values change. These elements are wrapped in special
comment nodes for debugging (to be true they are also used internally, so please do not edit them by hand):
`),
el(code, { src: fileURL("./components/examples/debugging/dom-reactive-mark.html"), page_id }),
el("p").append(T`
This is particularly useful when debugging why a reactive section isnt updating as expected.
You can inspect the elements between the comment nodes to see their current state and the
signal connections through \`__dde_reactive\` of the host element.
`),
el("h4", t`Identifying components in the DOM`),
el("p").append(T`
dd<el> marks components in the DOM with special comment nodes to help you identify component boundaries.
Components created with ${el("code", "el(MyComponent)")} are marked with comment nodes
${el("code", `<!--<dde:mark type="component" name="MyComponent" host="parentElement"/>-->`)} and
includes:
`),
el("ul").append(
el("li", t`type - Identifies the type of marker ("component", "reactive", …)`),
el("li", t`name - The name of the component function`),
el("li", t`host - Indicates whether the host is "this" (for DocumentFragments) or "parentElement"`),
),
el("h4", t`Identifying reactive elements in the DOM`),
el("p").append(T`
You can inspect (host) element relationships and bindings with signals in the DevTools console using
${el("code", "$0.__dde_reactive")} (for currently selected element). In the console you will see a list of
${el("code", `[ [ signal, listener ], element, property ]`)}, where:
`),
el("ul").append(
el("li", t`signal — the signal triggering the changes`),
el("li", t`listener — the listener function (this is an internal function for dd<el>)`),
el("li", t`element — the DOM element that is bound to the signal`),
el("li", t`property — the attribute or property name which is changing based on the signal`),
),
el("p").append(T`
…the structure of \`__dde_reactive\` utilizes the browsers behavior of packing the first field,
so you can see the element and property that changes in the console right away. These properties make it
easier to understand the reactive structure of your application when inspecting elements.
`),
el(example, { src: fileURL("./components/examples/signals/debugging-dom.js"), page_id }),
el("p", { className: "note" }).append(T`
${el("code", "<element>.__dde_reactive")} - An array property on DOM elements that tracks signal-to-element
relationships. This allows you to quickly identify which elements are reactive and what signals theyre
bound to. Each entry in the array contains:
`),
el("h4", t`Inspecting events and listeners in DevTools`),
el("p").append(T`
Modern browser DevTools provide built-in tools for inspecting event listeners attached to DOM elements.
For example, in Firefox and Chrome, you can:
`),
el("ol").append(
el("li", t`Select an element in the Elements/Inspector panel`),
el("li", t`Look for the "Event Listeners" tab or section`),
el("li", t`See all event listeners attached to the element, including those added by dd<el>`)
),
el("p").append(T`
Additionally, dd<el> provides special markers in the DOM that help identify debug information.
Look for comments with ${el("code", "dde:mark")}, ${el("code", "dde:disconnected")} and ${el("code",
"__dde_reactive")} which indicate components, reactive regions, and other internal relationships:
`),
el("figure").append(
el("img", {
src: "./assets/devtools.png",
alt: "Screenshot of DevTools showing usage of “event” button to inspect event listeners",
}),
el("figcaption", t`Firefox DevTools showing dd<el> debugging information with event listeners and reactive
markers`)
),
);
}