@sprlab/wccompiler 0.16.15 → 0.16.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +101 -0
- package/lib/codegen.js +11 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -359,6 +359,32 @@ The source expression calls the signal (`items()`) to read the current array. Su
|
|
|
359
359
|
<li each="item in items()" :key="item.id">{{item.name}}</li>
|
|
360
360
|
```
|
|
361
361
|
|
|
362
|
+
**Keyed Reconciliation with Full Reactivity:**
|
|
363
|
+
|
|
364
|
+
When using `:key`, the compiler optimizes rendering by reusing DOM nodes instead of destroying and recreating them. All dynamic bindings (text content, attributes, event handlers) are automatically updated when signals change, ensuring the UI always reflects the current data state.
|
|
365
|
+
|
|
366
|
+
```html
|
|
367
|
+
<!-- UI updates immediately when item.active changes -->
|
|
368
|
+
<li each="item in items()" :key="item.id">
|
|
369
|
+
<span>{{ item.name }}</span>
|
|
370
|
+
<span>{{ item.active ? '✓ Active' : '✗ Inactive' }}</span>
|
|
371
|
+
<button @click="() => toggleActive(item.id)">Toggle</button>
|
|
372
|
+
</li>
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
**Keyed Reconciliation with Full Reactivity:**
|
|
376
|
+
|
|
377
|
+
When using `:key`, the compiler optimizes rendering by reusing DOM nodes instead of destroying and recreating them. All dynamic bindings (text content, attributes, event handlers) are automatically updated when signals change, ensuring the UI always reflects the current data state.
|
|
378
|
+
|
|
379
|
+
```html
|
|
380
|
+
<!-- UI updates immediately when item.active changes -->
|
|
381
|
+
<li each="item in items()" :key="item.id">
|
|
382
|
+
<span>{{ item.name }}</span>
|
|
383
|
+
<span>{{ item.active ? '✓ Active' : '✗ Inactive' }}</span>
|
|
384
|
+
<button @click="() => toggleActive(item.id)">Toggle</button>
|
|
385
|
+
</li>
|
|
386
|
+
```
|
|
387
|
+
|
|
362
388
|
Numeric ranges are also supported:
|
|
363
389
|
|
|
364
390
|
```html
|
|
@@ -406,6 +432,81 @@ Directives work inside `each` blocks — including conditionals and nested loops
|
|
|
406
432
|
<div :style="{ color: textColor() }">...</div>
|
|
407
433
|
```
|
|
408
434
|
|
|
435
|
+
#### Class Directive (`:class`)
|
|
436
|
+
|
|
437
|
+
Supports multiple syntaxes for dynamic class binding:
|
|
438
|
+
|
|
439
|
+
**Object Syntax:**
|
|
440
|
+
```html
|
|
441
|
+
<div :class="{ active: isActive(), 'text-large': isLarge() }">Content</div>
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
**Ternary Expressions:**
|
|
445
|
+
```html
|
|
446
|
+
<div :class="theme() === 'light' ? 'light-theme' : 'dark-theme'">Content</div>
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
**Template Literals:**
|
|
450
|
+
```html
|
|
451
|
+
<div :class="`${theme()}-theme ${size()}-size`">Content</div>
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
**Mixed Static and Dynamic:**
|
|
455
|
+
```html
|
|
456
|
+
<div class="base-class" :class="isActive() ? 'active' : ''">Content</div>
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
All string literals are preserved correctly - signal names inside strings are NOT transformed.
|
|
460
|
+
|
|
461
|
+
#### Class Directive (`:class`)
|
|
462
|
+
|
|
463
|
+
Supports multiple syntaxes for dynamic class binding:
|
|
464
|
+
|
|
465
|
+
**Object Syntax:**
|
|
466
|
+
```html
|
|
467
|
+
<div :class="{ active: isActive(), 'text-large': isLarge() }">Content</div>
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
**Ternary Expressions:**
|
|
471
|
+
```html
|
|
472
|
+
<div :class="theme() === 'light' ? 'light-theme' : 'dark-theme'">Content</div>
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
**Template Literals:**
|
|
476
|
+
```html
|
|
477
|
+
<div :class="`${theme()}-theme ${size()}-size`">Content</div>
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
**Mixed Static and Dynamic:**
|
|
481
|
+
```html
|
|
482
|
+
<div class="base-class" :class="isActive() ? 'active' : ''">Content</div>
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
All string literals are preserved correctly - signal names inside strings are NOT transformed.
|
|
486
|
+
|
|
487
|
+
#### Style Directive (`:style`)
|
|
488
|
+
|
|
489
|
+
Supports single and multiple CSS properties:
|
|
490
|
+
|
|
491
|
+
**Single Property:**
|
|
492
|
+
```html
|
|
493
|
+
<div :style="{ color: textColor() }">Text</div>
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
**Multiple Properties:**
|
|
497
|
+
```html
|
|
498
|
+
<div :style="{ color: textColor(), fontSize: fontSize() + 'px', backgroundColor: bgColor() }">
|
|
499
|
+
Styled Text
|
|
500
|
+
</div>
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
**Kebab-case Properties:**
|
|
504
|
+
```html
|
|
505
|
+
<div :style="{ 'font-size': size() + 'px', 'background-color': bgColor() }">Text</div>
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
Object literal keys are preserved correctly - only values are transformed to reactive calls.
|
|
509
|
+
|
|
409
510
|
### Template Refs
|
|
410
511
|
|
|
411
512
|
```js
|
package/lib/codegen.js
CHANGED
|
@@ -1788,7 +1788,17 @@ export function generateComponent(parseResult, options = {}) {
|
|
|
1788
1788
|
lines.push(` __iter.forEach((${itemVar}, ${indexVar || '__idx'}) => {`);
|
|
1789
1789
|
lines.push(` const __key = ${keyExpr};`);
|
|
1790
1790
|
lines.push(' if (__oldMap.has(__key)) {');
|
|
1791
|
-
lines.push(' const
|
|
1791
|
+
lines.push(' const oldNode = __oldMap.get(__key);');
|
|
1792
|
+
|
|
1793
|
+
// BUG-0012 FIX: When reusing nodes, we must recreate them to get fresh effects
|
|
1794
|
+
// Old effects capture stale item references and fail on subsequent updates
|
|
1795
|
+
// Strategy: Remove old node, create fresh clone with new effects
|
|
1796
|
+
lines.push(' oldNode.remove();');
|
|
1797
|
+
lines.push(` const node = this.${vn}_tpl.content.cloneNode(true).firstChild;`);
|
|
1798
|
+
|
|
1799
|
+
// Setup bindings/events for the recreated node (uses 'node' variable)
|
|
1800
|
+
generateItemSetup(lines, forBlock, itemVar, indexVar, propNames, signalNamesSet, computedNamesSet, methodNames);
|
|
1801
|
+
|
|
1792
1802
|
lines.push(' __newMap.set(__key, node);');
|
|
1793
1803
|
lines.push(' __newNodes.push(node);');
|
|
1794
1804
|
lines.push(' __oldMap.delete(__key);');
|
package/package.json
CHANGED