fix(state): 修复 Select 绑定时序(by AI)
This commit is contained in:
parent
ea96c4ef22
commit
ad2a60e745
@ -1,5 +1,10 @@
|
|||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
|
|
||||||
|
## v1.0.25 (2026-07-13)
|
||||||
|
|
||||||
|
### 修复
|
||||||
|
- **Select 双向绑定时序**: 延后绑定值回写,确保模板动态生成选项时保留状态中的目标值,而非被浏览器默认选项覆盖。
|
||||||
|
|
||||||
## v1.0.23 (2026-07-06)
|
## v1.0.23 (2026-07-06)
|
||||||
|
|
||||||
### 修复
|
### 修复
|
||||||
|
|||||||
2
dist/state.js
vendored
2
dist/state.js
vendored
@ -451,7 +451,7 @@
|
|||||||
} else if (node.type === "radio") {
|
} else if (node.type === "radio") {
|
||||||
if (node.checked !== (node.value === String(result ?? ""))) node.checked = node.value === String(result ?? "");
|
if (node.checked !== (node.value === String(result ?? ""))) node.checked = node.value === String(result ?? "");
|
||||||
} else if ("value" in node && node.type !== "file") {
|
} else if ("value" in node && node.type !== "file") {
|
||||||
Promise.resolve().then(() => {
|
setTimeout(() => {
|
||||||
if (node.value !== String(result ?? "")) node.value = result;
|
if (node.value !== String(result ?? "")) node.value = result;
|
||||||
});
|
});
|
||||||
} else if (node.isContentEditable) {
|
} else if (node.isContentEditable) {
|
||||||
|
|||||||
2
dist/state.min.js
vendored
2
dist/state.min.js
vendored
File diff suppressed because one or more lines are too long
@ -280,7 +280,10 @@ export function _updateBinding(binding) {
|
|||||||
} else if (node.type === 'radio') {
|
} else if (node.type === 'radio') {
|
||||||
if (node.checked !== (node.value === String(result ?? ''))) node.checked = (node.value === String(result ?? ''));
|
if (node.checked !== (node.value === String(result ?? ''))) node.checked = (node.value === String(result ?? ''));
|
||||||
} else if ('value' in node && node.type !== 'file') {
|
} else if ('value' in node && node.type !== 'file') {
|
||||||
Promise.resolve().then(() => { if (node.value !== String(result ?? '')) node.value = result; });
|
// A select may receive its bound value before template-rendered
|
||||||
|
// options exist. Run after the current render turn so adding options
|
||||||
|
// cannot replace the model value with the browser's default option.
|
||||||
|
setTimeout(() => { if (node.value !== String(result ?? '')) node.value = result; });
|
||||||
} else if (node.isContentEditable) {
|
} else if (node.isContentEditable) {
|
||||||
if (node.innerHTML !== String(result ?? '')) node.innerHTML = result;
|
if (node.innerHTML !== String(result ?? '')) node.innerHTML = result;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -62,7 +62,16 @@ window.testDom = async function() {
|
|||||||
input.dispatchEvent(new Event('input'));
|
input.dispatchEvent(new Event('input'));
|
||||||
if (state.val !== '') throw new Error('$bind must preserve an empty text value');
|
if (state.val !== '') throw new Error('$bind must preserve an empty text value');
|
||||||
|
|
||||||
// 6. Double evaluation ($$ prefix)
|
// 6. A select bound before its template-rendered options must retain the
|
||||||
|
// model value instead of writing the browser-selected default back.
|
||||||
|
document.body.innerHTML = '<select id="test-select" $bind="state.selected"><template $each="state.options"><option $text="item" $value="item"></option></template></select>';
|
||||||
|
state.selected = 'second';
|
||||||
|
state.options = ['first', 'second'];
|
||||||
|
__unsafeRefreshState(document.documentElement);
|
||||||
|
await wait();
|
||||||
|
if ($('#test-select').value !== 'second' || state.selected !== 'second') throw new Error('$bind select must retain its value after rendering options');
|
||||||
|
|
||||||
|
// 7. Double evaluation ($$ prefix)
|
||||||
console.log('Testing double evaluation ($$)...');
|
console.log('Testing double evaluation ($$)...');
|
||||||
document.body.innerHTML = `
|
document.body.innerHTML = `
|
||||||
<div id="double-eval-root">
|
<div id="double-eval-root">
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user