fix(dom): correctly bind context for auto-created templates in / and optimize traversal
This commit is contained in:
parent
b8652c357e
commit
9d14dbe233
@ -1,5 +1,10 @@
|
||||
# CHANGELOG
|
||||
|
||||
## v1.0.12 (2026-05-25)
|
||||
|
||||
### 修复
|
||||
- **上下文绑定**: 修复了在对非 `template` 节点使用 `$if` 或 `$each` 指令时,框架自动创建 `<template>` 会过早转移未初始化的父级上下文,并在脱离 DOM 树后跳过深度扫描,导致 `this` 指向丢失为自身 DOM 节点的严重 Bug。同时优化了向上寻找上下文的遍历路径,避免了双重循环的性能开销。
|
||||
|
||||
## v1.0.11 (2026-05-21)
|
||||
|
||||
### 核心优化
|
||||
|
||||
21
dist/state.js
vendored
21
dist/state.js
vendored
@ -470,6 +470,18 @@ const _scanTree = (node, scanObj = {}) => {
|
||||
});
|
||||
node._stTranslated = true;
|
||||
}
|
||||
let resolvedThisObj = node._thisObj;
|
||||
let resolvedRef = node._ref;
|
||||
if (resolvedThisObj === void 0 || resolvedRef === void 0) {
|
||||
let curr = node;
|
||||
while (curr && (resolvedThisObj === void 0 || resolvedRef === void 0)) {
|
||||
if (resolvedThisObj === void 0 && curr._thisObj !== void 0) resolvedThisObj = curr._thisObj;
|
||||
if (resolvedRef === void 0 && curr._ref !== void 0) resolvedRef = { ...curr._ref };
|
||||
curr = curr.parentNode;
|
||||
}
|
||||
}
|
||||
if (resolvedThisObj === void 0) resolvedThisObj = scanObj.thisObj;
|
||||
if (resolvedRef === void 0) resolvedRef = scanObj.extendVars;
|
||||
if (node.tagName !== "TEMPLATE" && (node.hasAttribute("$if") || node.hasAttribute("$each") || node.hasAttribute("st-if") || node.hasAttribute("st-each"))) {
|
||||
const template = document.createElement("TEMPLATE");
|
||||
const attrs = Array.from(node.attributes).filter((attr) => ["$if", "$each", "st-if", "st-each"].includes(attr.name) || (node.hasAttribute("$each") || node.hasAttribute("st-each")) && ["as", "index"].includes(attr.name));
|
||||
@ -479,7 +491,9 @@ const _scanTree = (node, scanObj = {}) => {
|
||||
});
|
||||
node.parentNode.insertBefore(template, node);
|
||||
template.content.appendChild(node);
|
||||
template._ref = node._ref;
|
||||
template._ref = resolvedRef;
|
||||
template._thisObj = resolvedThisObj;
|
||||
_scanTree(template, scanObj);
|
||||
return;
|
||||
}
|
||||
if (node.tagName === "TEMPLATE" && (node.hasAttribute("$if") || node.hasAttribute("st-if")) && (node.hasAttribute("$each") || node.hasAttribute("st-each"))) {
|
||||
@ -496,7 +510,8 @@ const _scanTree = (node, scanObj = {}) => {
|
||||
}
|
||||
Array.from(node.content.childNodes).forEach((child) => template.content.appendChild(child));
|
||||
node.content.appendChild(template);
|
||||
template._ref = node._ref;
|
||||
template._ref = resolvedRef;
|
||||
template._thisObj = resolvedThisObj;
|
||||
}
|
||||
if (node.tagName === "IMG" && (node.hasAttribute("src") || node.hasAttribute("_src") || node.hasAttribute("$src"))) {
|
||||
const imgNode = node;
|
||||
@ -526,7 +541,7 @@ const _scanTree = (node, scanObj = {}) => {
|
||||
Object.assign(node._ref, node._refExt);
|
||||
}
|
||||
if (scanObj.extendVars) Object.assign(node._ref, scanObj.extendVars);
|
||||
_parseNode(node, scanObj);
|
||||
_parseNode(node, { ...scanObj });
|
||||
const nodes = [...node.childNodes || []];
|
||||
const nextScanObj = { thisObj: scanObj.thisObj, extendVars: { ...node._ref } };
|
||||
nodes.forEach((child) => {
|
||||
|
||||
2
dist/state.min.js
vendored
2
dist/state.min.js
vendored
File diff suppressed because one or more lines are too long
@ -1,7 +1,6 @@
|
||||
{
|
||||
"name": "@web/state",
|
||||
"version": "1.0.10",
|
||||
|
||||
"version": "1.0.12",
|
||||
"type": "module",
|
||||
"main": "dist/state.js",
|
||||
"module": "dist/state.js",
|
||||
@ -19,4 +18,4 @@
|
||||
"terser": "^5.47.1",
|
||||
"vite": "^5.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
24
src/dom.js
24
src/dom.js
@ -309,13 +309,30 @@ export const _scanTree = (node, scanObj = {}) => {
|
||||
node._stTranslated = true;
|
||||
}
|
||||
|
||||
let resolvedThisObj = node._thisObj;
|
||||
let resolvedRef = node._ref;
|
||||
|
||||
if (resolvedThisObj === undefined || resolvedRef === undefined) {
|
||||
let curr = node;
|
||||
while (curr && (resolvedThisObj === undefined || resolvedRef === undefined)) {
|
||||
if (resolvedThisObj === undefined && curr._thisObj !== undefined) resolvedThisObj = curr._thisObj;
|
||||
if (resolvedRef === undefined && curr._ref !== undefined) resolvedRef = { ...curr._ref };
|
||||
curr = curr.parentNode;
|
||||
}
|
||||
}
|
||||
|
||||
if (resolvedThisObj === undefined) resolvedThisObj = scanObj.thisObj;
|
||||
if (resolvedRef === undefined) resolvedRef = scanObj.extendVars;
|
||||
|
||||
if (node.tagName !== 'TEMPLATE' && (node.hasAttribute('$if') || node.hasAttribute('$each') || node.hasAttribute('st-if') || node.hasAttribute('st-each'))) {
|
||||
const template = document.createElement('TEMPLATE');
|
||||
const attrs = Array.from(node.attributes).filter(attr => ['$if', '$each', 'st-if', 'st-each'].includes(attr.name) || ((node.hasAttribute('$each') || node.hasAttribute('st-each')) && ['as', 'index'].includes(attr.name)));
|
||||
attrs.forEach(attr => { template.setAttribute(attr.name, attr.value); node.removeAttribute(attr.name); });
|
||||
node.parentNode.insertBefore(template, node);
|
||||
template.content.appendChild(node);
|
||||
template._ref = node._ref;
|
||||
template._ref = resolvedRef;
|
||||
template._thisObj = resolvedThisObj; // Crucial fix: Propagate context
|
||||
_scanTree(template, scanObj);
|
||||
return;
|
||||
}
|
||||
if (node.tagName === 'TEMPLATE' && (node.hasAttribute('$if') || node.hasAttribute('st-if')) && (node.hasAttribute('$each') || node.hasAttribute('st-each'))) {
|
||||
@ -329,7 +346,8 @@ export const _scanTree = (node, scanObj = {}) => {
|
||||
}
|
||||
Array.from(node.content.childNodes).forEach(child => template.content.appendChild(child));
|
||||
node.content.appendChild(template);
|
||||
template._ref = node._ref;
|
||||
template._ref = resolvedRef;
|
||||
template._thisObj = resolvedThisObj; // Crucial fix: Propagate context
|
||||
}
|
||||
|
||||
if (node.tagName === 'IMG' && (node.hasAttribute('src') || node.hasAttribute('_src') || node.hasAttribute('$src'))) {
|
||||
@ -362,7 +380,7 @@ export const _scanTree = (node, scanObj = {}) => {
|
||||
}
|
||||
if (scanObj.extendVars) Object.assign(node._ref, scanObj.extendVars);
|
||||
|
||||
_parseNode(node, scanObj);
|
||||
_parseNode(node, { ...scanObj });
|
||||
|
||||
const nodes = [...(node.childNodes || [])];
|
||||
const nextScanObj = { thisObj: scanObj.thisObj, extendVars: { ...node._ref } };
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user