Fixed AutoForm field mounting binding issues. By: AICoder

This commit is contained in:
AI Engineer 2026-06-05 20:07:18 +08:00
parent f1397a4776
commit b26df1112d
8 changed files with 19 additions and 7 deletions

View File

@ -1,9 +1,14 @@
# CHANGELOG # CHANGELOG
## v1.0.16 (2026-06-05)
### 修复
- **挂载节点绑定失效**: 修复了在离线/内存中提早调用 `_scanTree` 时子节点被错打 `_stScanned` 标记,导致节点被真正挂载(`isConnected`)时因 `_stScanned` 为真而被 MutationObserver 跳过,从而使其上的表达式绑定未被计算的 Bug。现在只有当节点真正 connected 时才记录 `_stScanned = true`,且在模板包装节点时主动删除原有的 `_stScanned` 标记。
## v1.0.15 (2026-06-05) ## v1.0.15 (2026-06-05)
### 修复 ### 修复
- **挂载节点绑定失效**: 修复了在离线/内存中提早调用 `_scanTree` 时子节点被打上 `_stScanned` 标记,导致节点被真正挂载(`isConnected`)时因 `_stScanned` 为真而被 MutationObserver 跳过,从而使其上的表达式绑定未被计算的 Bug。现在只有当节点真正 connected 时才记录 `_stScanned = true` - Bump package version and prep tags.
## v1.0.14 (2026-06-05) ## v1.0.14 (2026-06-05)

4
dist/state.js vendored
View File

@ -477,7 +477,6 @@
return; return;
} }
if (node.nodeType !== 1) return; if (node.nodeType !== 1) return;
if (node.isConnected) node._stScanned = true;
if (!node._stTranslated) { if (!node._stTranslated) {
Array.from(node.attributes).forEach((attr) => { Array.from(node.attributes).forEach((attr) => {
if (!attr.name.startsWith("$") && !attr.name.startsWith("st-") && !attr.name.startsWith(".")) { if (!attr.name.startsWith("$") && !attr.name.startsWith("st-") && !attr.name.startsWith(".")) {
@ -512,9 +511,11 @@
template.content.appendChild(node); template.content.appendChild(node);
template._ref = resolvedRef; template._ref = resolvedRef;
template._thisObj = resolvedThisObj; template._thisObj = resolvedThisObj;
delete node._stScanned;
_scanTree(template, scanObj); _scanTree(template, scanObj);
return; return;
} }
if (node.isConnected) node._stScanned = true;
if (node.tagName === "TEMPLATE" && (node.hasAttribute("$if") || node.hasAttribute("st-if") || node.hasAttribute("$$if") || node.hasAttribute("st-st-if")) && (node.hasAttribute("$each") || node.hasAttribute("st-each") || node.hasAttribute("$$each") || node.hasAttribute("st-st-each"))) { if (node.tagName === "TEMPLATE" && (node.hasAttribute("$if") || node.hasAttribute("st-if") || node.hasAttribute("$$if") || node.hasAttribute("st-st-if")) && (node.hasAttribute("$each") || node.hasAttribute("st-each") || node.hasAttribute("$$each") || node.hasAttribute("st-st-each"))) {
const template = document.createElement("TEMPLATE"); const template = document.createElement("TEMPLATE");
const attrs = Array.from(node.attributes).filter((attr2) => triggerAttrs.includes(attr2.name)); const attrs = Array.from(node.attributes).filter((attr2) => triggerAttrs.includes(attr2.name));
@ -697,6 +698,7 @@
mutations.forEach((mutation) => { mutations.forEach((mutation) => {
mutation.addedNodes.forEach((newNode) => { mutation.addedNodes.forEach((newNode) => {
if (newNode.isConnected && newNode.nodeType === 1 && !newNode._stScanned) { if (newNode.isConnected && newNode.nodeType === 1 && !newNode._stScanned) {
newNode._stScanned = true;
_scanTree(newNode); _scanTree(newNode);
} }
}); });

2
dist/state.min.js vendored

File diff suppressed because one or more lines are too long

2
dist/state.min.mjs vendored

File diff suppressed because one or more lines are too long

4
dist/state.mjs vendored
View File

@ -473,7 +473,6 @@ const _scanTree = (node, scanObj = {}) => {
return; return;
} }
if (node.nodeType !== 1) return; if (node.nodeType !== 1) return;
if (node.isConnected) node._stScanned = true;
if (!node._stTranslated) { if (!node._stTranslated) {
Array.from(node.attributes).forEach((attr) => { Array.from(node.attributes).forEach((attr) => {
if (!attr.name.startsWith("$") && !attr.name.startsWith("st-") && !attr.name.startsWith(".")) { if (!attr.name.startsWith("$") && !attr.name.startsWith("st-") && !attr.name.startsWith(".")) {
@ -508,9 +507,11 @@ const _scanTree = (node, scanObj = {}) => {
template.content.appendChild(node); template.content.appendChild(node);
template._ref = resolvedRef; template._ref = resolvedRef;
template._thisObj = resolvedThisObj; template._thisObj = resolvedThisObj;
delete node._stScanned;
_scanTree(template, scanObj); _scanTree(template, scanObj);
return; return;
} }
if (node.isConnected) node._stScanned = true;
if (node.tagName === "TEMPLATE" && (node.hasAttribute("$if") || node.hasAttribute("st-if") || node.hasAttribute("$$if") || node.hasAttribute("st-st-if")) && (node.hasAttribute("$each") || node.hasAttribute("st-each") || node.hasAttribute("$$each") || node.hasAttribute("st-st-each"))) { if (node.tagName === "TEMPLATE" && (node.hasAttribute("$if") || node.hasAttribute("st-if") || node.hasAttribute("$$if") || node.hasAttribute("st-st-if")) && (node.hasAttribute("$each") || node.hasAttribute("st-each") || node.hasAttribute("$$each") || node.hasAttribute("st-st-each"))) {
const template = document.createElement("TEMPLATE"); const template = document.createElement("TEMPLATE");
const attrs = Array.from(node.attributes).filter((attr2) => triggerAttrs.includes(attr2.name)); const attrs = Array.from(node.attributes).filter((attr2) => triggerAttrs.includes(attr2.name));
@ -693,6 +694,7 @@ if (typeof document !== "undefined") {
mutations.forEach((mutation) => { mutations.forEach((mutation) => {
mutation.addedNodes.forEach((newNode) => { mutation.addedNodes.forEach((newNode) => {
if (newNode.isConnected && newNode.nodeType === 1 && !newNode._stScanned) { if (newNode.isConnected && newNode.nodeType === 1 && !newNode._stScanned) {
newNode._stScanned = true;
_scanTree(newNode); _scanTree(newNode);
} }
}); });

View File

@ -1,6 +1,6 @@
{ {
"name": "@apigo.cc/state", "name": "@apigo.cc/state",
"version": "1.0.15", "version": "1.0.16",
"type": "module", "type": "module",
"main": "dist/state.js", "main": "dist/state.js",
"module": "dist/state.js", "module": "dist/state.js",

View File

@ -308,7 +308,6 @@ export const _scanTree = (node, scanObj = {}) => {
node._stTranslated = true; return; node._stTranslated = true; return;
} }
if (node.nodeType !== 1) return; if (node.nodeType !== 1) return;
if (node.isConnected) node._stScanned = true;
if (!node._stTranslated) { if (!node._stTranslated) {
Array.from(node.attributes).forEach(attr => { Array.from(node.attributes).forEach(attr => {
@ -345,9 +344,12 @@ export const _scanTree = (node, scanObj = {}) => {
template.content.appendChild(node); template.content.appendChild(node);
template._ref = resolvedRef; template._ref = resolvedRef;
template._thisObj = resolvedThisObj; // Crucial fix: Propagate context template._thisObj = resolvedThisObj; // Crucial fix: Propagate context
delete node._stScanned;
_scanTree(template, scanObj); _scanTree(template, scanObj);
return; return;
} }
if (node.isConnected) node._stScanned = true;
if (node.tagName === 'TEMPLATE' && (node.hasAttribute('$if') || node.hasAttribute('st-if') || node.hasAttribute('$$if') || node.hasAttribute('st-st-if')) && (node.hasAttribute('$each') || node.hasAttribute('st-each') || node.hasAttribute('$$each') || node.hasAttribute('st-st-each'))) { if (node.tagName === 'TEMPLATE' && (node.hasAttribute('$if') || node.hasAttribute('st-if') || node.hasAttribute('$$if') || node.hasAttribute('st-st-if')) && (node.hasAttribute('$each') || node.hasAttribute('st-each') || node.hasAttribute('$$each') || node.hasAttribute('st-st-each'))) {
const template = document.createElement('TEMPLATE'); const template = document.createElement('TEMPLATE');
const attrs = Array.from(node.attributes).filter(attr => triggerAttrs.includes(attr.name)); const attrs = Array.from(node.attributes).filter(attr => triggerAttrs.includes(attr.name));

View File

@ -29,6 +29,7 @@ if (typeof document !== 'undefined') {
mutations.forEach(mutation => { mutations.forEach(mutation => {
mutation.addedNodes.forEach(newNode => { mutation.addedNodes.forEach(newNode => {
if (newNode.isConnected && newNode.nodeType === 1 && !newNode._stScanned) { if (newNode.isConnected && newNode.nodeType === 1 && !newNode._stScanned) {
newNode._stScanned = true;
_scanTree(newNode); _scanTree(newNode);
} }
}); });