我在这里有点困惑,不幸的是我无法在 svelte 的不和谐 channel 上找到任何解决方案,所以我开始了......
我有两个类的一个相当基本的例子,让它们成为 App
和 Comp
.App
创建一个 Comp
实例,然后更新此实例的 value
单击按钮后。
Comp 实例应将此值设置为不同的变量( inputValue
),并在更改该变量时触发 validate(inputValue)
这是 react 性的。这是一个 REPL:https://svelte.dev/repl/1df2eb0e67b240e9b1449e52fb26eb14?version=3.25.1
App.svelte:
<script>
import Comp from './Comp.svelte';
let value = 'now: ' + Date.now();
function clickHandler(e) {
value = 'now ' + Date.now();
}
</script>
<Comp
bind:value={value}
/>
<button type="button" on:click={clickHandler}>change value</button>
比较 slim :<script>
import { onMount } from 'svelte';
export let value;
let rendered = false;
let inputValue = '';
$: validate(inputValue); // This doesn't execute. Why?
function validate(val) {
console.log('validation:', val);
}
onMount(() => {
rendered = true;
});
$: if (rendered) {
updateInputValue(value);
}
function updateInputValue(val) {
console.log('updateInputValue called!');
if (!value) {
inputValue = '';
}
else {
inputValue = value;
}
}
</script>
<input type="text" bind:value={inputValue}>
因此,一旦更改了值:if (rendered) {...}
条件称为 updateInputValue
被调用并且inputValue
被改变。 HTML 输入元素更新为此值。 validate(inputValue)
从未对这种变化使用react - 为什么? 如果我省略对
updateInputValue
的额外调用 react 中的函数if (rendered)
条件和放置updateInputValue
函数体的代码直接到条件,然后validate(inputValue)
被正确触发,即:// works like this
$: if (rendered) {
if (!value) {
inputValue = '';
}
else {
inputValue = value;
}
}
那么为什么在函数中更新它不起作用呢?
最佳答案
@johannchopin 的 answer揭示了这个问题。
您可以阅读my blogpost for slightly in-depth explanation of how reactive declaration works ,这里是 tl;博士:
svelte 批处理所有更改以在下一个更新周期中更新它们,并且在更新 DOM 之前,它将执行响应式声明以更新响应式变量。
响应式(Reactive)声明是批量执行的,每个声明执行一次。一些声明相互依赖,例如:
let count = 0;
$: double = count * 2;
$: quadruple = double * 2;
在这种情况下,quadruple
取决于 double
.所以不管你的 react 声明的顺序如何,$: double = count * 2;
之前 $: quadruple = double * 2
或者反过来,前者应该是和 将是 在后者之前执行。slim 将排序 依赖顺序中的声明。
在彼此没有依赖关系的情况下:
$: validate(inputValue);
$: if (rendered) updateInputValue(value);
第一条语句取决于 validate
和 inputValue
, 第二条语句取决于 rendered
, updateInputValue
和 value
,声明保持原样。现在,了解了响应式(Reactive)声明的这两种行为,让我们来看看你的 REPL .
当你改变
inputValue
, rendered
或 value
, Svelte 将批量更改,并开始新的更新周期。在更新 DOM 之前,Svelte 将一次性执行所有的响应式(Reactive)声明。
因为
validate(inputValue);
之间没有依赖关系和 if (rendered) updateInputValue(value);
语句,(如前所述),它们将按顺序执行。如果您更改
rendered
或 value
只有,第一条语句( validate(inputValue)
)不会被执行,同样,如果你改变 inputValue
第二条语句 ( if (rendered) updateInputValue(value)
) 不会被执行。现在,在
updateInputValue
您更改 inputValue
的值,但因为我们已经处于更新周期,我们不会开始一个新的。这通常不是问题,因为如果我们按照依赖顺序对响应式声明进行排序,更新所依赖变量的语句将在依赖变量的语句之前执行。
因此,知道出了什么问题,您可以寻求一些“解决方案”。
请参阅此 REPL 中订购响应式(Reactive)声明的区别
因此,将您的 REPL 更改为:
$: if (rendered) {
updateInputValue(value);
}
$: validate(inputValue);
See REPL$: validate(inputValue);
$: if (rendered) {
inputValue = updateInputValue(value);
}
function updateInputValue(val) {
console.log('updateInputValue called!');
if (!value) {
return '';
}
else {
return value;
}
}
See REPL
关于javascript - 当函数中的变量更改时,不会触发 Svelte react 性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63934543/