如何像 useEffect 一样监听 svelte 的状态变化
How to listen the state changes in svelte like useEffect
我读过一些关于状态变化监听器的文章,由于我是 svelte 环境的初学者,我不知道什么是最有效的监听状态变化的方法。
让我们将状态变量设为 X
和 Y
方法一:
$: if (X||Y) {
console.log("yes");
}
方法二:
使用 afterUpdate
和 onDestroy
的组合
回复:https://svelte.dev/repl/300c16ee38af49e98261eef02a9b04a8?version=3.38.2
import { afterUpdate, onDestroy } from 'svelte';
export function useEffect(cb, deps) {
let cleanup;
function apply() {
if (cleanup) cleanup();
cleanup = cb();
}
if (deps) {
let values = [];
afterUpdate(() => {
const new_values = deps();
if (new_values.some((value, i) => value !== values[i])) {
apply();
values = new_values;
}
});
} else {
// no deps = always run
afterUpdate(apply);
}
onDestroy(() => {
if (cleanup) cleanup();
});
}
方法三:
使用writable
和subscribe
<script>
import { writable } from 'svelte/store';
const X = writable(0);
const Y = writable(0);
X.subscribe(value => {
console.log("X was changed", value);
});
Y.subscribe(value => {
console.log("Y was changed", value);
});
</script>
<button on:click={(e)=>{
X.update((val)=>val++)
}}>Change X</button>
<button on:click={(e)=>{
Y.update((val)=>val++)
}}>Change Y</button>
响应式语句
Svelte 没有 useEffect 的等效项。相反,Svelte 有响应式语句。
// Svelte
// doubled will always be twice of single. If single updates, doubled will run again.
$: doubled = single * 2
// equivalent to this React
let single = 0
const [doubled, setDoubled] = useState(single * 2)
useEffect(() => {
setDoubled(single * 2)
}, [single])
这看起来很神奇,因为您没有定义依赖项或拆卸函数,但 Svelte 会处理所有这些事情。 Svelte 足够聪明,可以找出依赖关系,并且只根据需要 运行 每个反应语句。
因此,如果您想在每次值更新时 运行 回调,您可以简单地执行此操作。
<script>
let value = ''
$: console.log(value)
</script>
<input type='text' name='name' bind:value />
简而言之,这将在每次输入值更改时控制台记录输入值。
重新创建您的建议
方法一
这已经尽可能简洁了,除非我需要更复杂的东西,否则这是我监听状态变化的首选方法。
$: if(x || y) console.log('yes')
不过请注意,这里可能存在一个细微的错误。如果 x
或 y
都是真值然后变为假值(例如,它们都变成空字符串),则此语句不会 运行.
方法二
在这里,您基本上重新创建了 React 的 useEffect
。这行得通,但是您可以使用反应式语句大大简化 REPL 中的实现。
<script>
let count = 1;
$: console.log(count)
</script>
<input type="number" bind:value={count}>
方法三
Stores 非常适合在不使用 props 或上下文的情况下在组件之间传递数据。查看此答案了解更多信息:
不过,在这种情况下,我们可以(再次)使用常规反应式上下文来简化一切。
<script>
let x = 0
let y = 0
$: console.log('x was changed', x)
$: console.log('y was changed', y)
</script>
<button on:click={() => x++}>Change x</button>
<button on:click={() => y++}>Change x</button>
我在 [=25 中也有比较 React 的 context
/useEffect
和 Svelte 的 context
/stores
/reactive 语句的详细答案=]
我读过一些关于状态变化监听器的文章,由于我是 svelte 环境的初学者,我不知道什么是最有效的监听状态变化的方法。
让我们将状态变量设为 X
和 Y
方法一:
$: if (X||Y) {
console.log("yes");
}
方法二:
使用 afterUpdate
和 onDestroy
回复:https://svelte.dev/repl/300c16ee38af49e98261eef02a9b04a8?version=3.38.2
import { afterUpdate, onDestroy } from 'svelte';
export function useEffect(cb, deps) {
let cleanup;
function apply() {
if (cleanup) cleanup();
cleanup = cb();
}
if (deps) {
let values = [];
afterUpdate(() => {
const new_values = deps();
if (new_values.some((value, i) => value !== values[i])) {
apply();
values = new_values;
}
});
} else {
// no deps = always run
afterUpdate(apply);
}
onDestroy(() => {
if (cleanup) cleanup();
});
}
方法三:
使用writable
和subscribe
<script>
import { writable } from 'svelte/store';
const X = writable(0);
const Y = writable(0);
X.subscribe(value => {
console.log("X was changed", value);
});
Y.subscribe(value => {
console.log("Y was changed", value);
});
</script>
<button on:click={(e)=>{
X.update((val)=>val++)
}}>Change X</button>
<button on:click={(e)=>{
Y.update((val)=>val++)
}}>Change Y</button>
响应式语句
Svelte 没有 useEffect 的等效项。相反,Svelte 有响应式语句。
// Svelte
// doubled will always be twice of single. If single updates, doubled will run again.
$: doubled = single * 2
// equivalent to this React
let single = 0
const [doubled, setDoubled] = useState(single * 2)
useEffect(() => {
setDoubled(single * 2)
}, [single])
这看起来很神奇,因为您没有定义依赖项或拆卸函数,但 Svelte 会处理所有这些事情。 Svelte 足够聪明,可以找出依赖关系,并且只根据需要 运行 每个反应语句。
因此,如果您想在每次值更新时 运行 回调,您可以简单地执行此操作。
<script>
let value = ''
$: console.log(value)
</script>
<input type='text' name='name' bind:value />
简而言之,这将在每次输入值更改时控制台记录输入值。
重新创建您的建议
方法一
这已经尽可能简洁了,除非我需要更复杂的东西,否则这是我监听状态变化的首选方法。
$: if(x || y) console.log('yes')
不过请注意,这里可能存在一个细微的错误。如果 x
或 y
都是真值然后变为假值(例如,它们都变成空字符串),则此语句不会 运行.
方法二
在这里,您基本上重新创建了 React 的 useEffect
。这行得通,但是您可以使用反应式语句大大简化 REPL 中的实现。
<script>
let count = 1;
$: console.log(count)
</script>
<input type="number" bind:value={count}>
方法三
Stores 非常适合在不使用 props 或上下文的情况下在组件之间传递数据。查看此答案了解更多信息:
不过,在这种情况下,我们可以(再次)使用常规反应式上下文来简化一切。
<script>
let x = 0
let y = 0
$: console.log('x was changed', x)
$: console.log('y was changed', y)
</script>
<button on:click={() => x++}>Change x</button>
<button on:click={() => y++}>Change x</button>
我在 context
/useEffect
和 Svelte 的 context
/stores
/reactive 语句的详细答案=]