信号是一个具有两个主要目标的表现国家管理库:
阅读公告文章,以了解有关哪些问题解决的更多信息以及如何解决。
# Just the core library
npm install @preact/signals-core
# If you're using Preact
npm install @preact/signals
# If you're using React
npm install @preact/signals-react
# If you're using Svelte
npm install @preact/signals-core
signal(initialValue)
signal.peek()
computed(fn)
effect(fn)
batch(fn)
untracked(fn)
信号库公开了四个功能,这是建模您可以想到的任何业务逻辑的构建块。
signal(initialValue)
signal
功能会产生一个新信号。信号是一个可以随时间变化的值的容器。您可以通过访问其.value
属性来读取信号的值或订阅值更新。
import { signal } from "@preact/signals-core" ;
const counter = signal ( 0 ) ;
// Read value from signal, logs: 0
console . log ( counter . value ) ;
// Write to a signal
counter . value = 1 ;
写入信号是通过设置其.value
属性来完成的。更改信号的值同步更新了取决于该信号的每个计算和效果,以确保您的应用程序状态始终保持一致。
signal.peek()
在极少数情况下,您应根据上一个值将其写入另一个信号,但是您不希望订阅该信号的效果,您可以通过signal.peek()
读取信号的先前值。
const counter = signal ( 0 ) ;
const effectCount = signal ( 0 ) ;
effect ( ( ) => {
console . log ( counter . value ) ;
// Whenever this effect is triggered, increase `effectCount`.
// But we don't want this signal to react to `effectCount`
effectCount . value = effectCount . peek ( ) + 1 ;
} ) ;
请注意,如果您确实需要它,则应仅使用signal.peek()
。通过signal.value
读取信号的值。值是大多数情况下的首选方式。
computed(fn)
数据通常源自其他现有数据。 computed
函数使您可以将多个信号的值结合到一个可以反应甚至由其他计算机使用的新信号中。当从计算的回调更改中访问的信号时,重新执行了计算的回调,其新返回值将成为计算信号的值。
import { signal , computed } from "@preact/signals-core" ;
const name = signal ( "Jane" ) ;
const surname = signal ( "Doe" ) ;
const fullName = computed ( ( ) => name . value + " " + surname . value ) ;
// Logs: "Jane Doe"
console . log ( fullName . value ) ;
// Updates flow through computed, but only if someone
// subscribes to it. More on that later.
name . value = "John" ;
// Logs: "John Doe"
console . log ( fullName . value ) ;
computed
的回调函数中访问的任何信号将自动订阅并跟踪为计算信号的依赖性。
effect(fn)
effect
函数是使所有事物都反应的最后一部分。当您在其回调函数中访问信号时,该信号和所述信号的每个依赖性将被激活并订阅。在这方面,它与computed(fn)
非常相似。默认情况下,所有更新都很懒惰,因此在您访问信号内部effect
之前,什么都不会更新。
import { signal , computed , effect } from "@preact/signals-core" ;
const name = signal ( "Jane" ) ;
const surname = signal ( "Doe" ) ;
const fullName = computed ( ( ) => name . value + " " + surname . value ) ;
// Logs: "Jane Doe"
effect ( ( ) => console . log ( fullName . value ) ) ;
// Updating one of its dependencies will automatically trigger
// the effect above, and will print "John Doe" to the console.
name . value = "John" ;
您可以通过调用返回的功能来破坏效果并取消订阅其订阅的所有信号。
import { signal , computed , effect } from "@preact/signals-core" ;
const name = signal ( "Jane" ) ;
const surname = signal ( "Doe" ) ;
const fullName = computed ( ( ) => name . value + " " + surname . value ) ;
// Logs: "Jane Doe"
const dispose = effect ( ( ) => console . log ( fullName . value ) ) ;
// Destroy effect and subscriptions
dispose ( ) ;
// Update does nothing, because no one is subscribed anymore.
// Even the computed `fullName` signal won't change, because it knows
// that no one listens to it.
surname . value = "Doe 2" ;
效果回调可能会返回清理功能。在接下来要调用效果回调的效果回调或效果被处置时,清理功能会运行一次。
import { signal , effect } from "@preact/signals-core" ;
const count = signal ( 0 ) ;
const dispose = effect ( ( ) => {
const c = count . value ;
return ( ) => console . log ( `cleanup ${ c } ` ) ;
} ) ;
// Logs: cleanup 0
count . value = 1 ;
// Logs: cleanup 1
dispose ( ) ;
batch(fn)
batch
功能允许您将多个信号写入一个单个更新中,该更新在回调完成时在末尾触发。
import { signal , computed , effect , batch } from "@preact/signals-core" ;
const name = signal ( "Jane" ) ;
const surname = signal ( "Doe" ) ;
const fullName = computed ( ( ) => name . value + " " + surname . value ) ;
// Logs: "Jane Doe"
effect ( ( ) => console . log ( fullName . value ) ) ;
// Combines both signal writes into one update. Once the callback
// returns the `effect` will trigger and we'll log "Foo Bar"
batch ( ( ) => {
name . value = "Foo" ;
surname . value = "Bar" ;
} ) ;
当您访问回调内部写入的信号,或访问由另一个信号无效的计算信号时,我们只会更新必要的依赖项,以获取您从中读取的信号的当前值。所有其他无效的信号将在回调函数的末尾进行更新。
import { signal , computed , effect , batch } from "@preact/signals-core" ;
const counter = signal ( 0 ) ;
const double = computed ( ( ) => counter . value * 2 ) ;
const triple = computed ( ( ) => counter . value * 3 ) ;
effect ( ( ) => console . log ( double . value , triple . value ) ) ;
batch ( ( ) => {
counter . value = 1 ;
// Logs: 2, despite being inside batch, but `triple`
// will only update once the callback is complete
console . log ( double . value ) ;
} ) ;
// Now we reached the end of the batch and call the effect
批处理可以嵌套,并在最外面的批次调用完成后汇总更新。
import { signal , computed , effect , batch } from "@preact/signals-core" ;
const counter = signal ( 0 ) ;
effect ( ( ) => console . log ( counter . value ) ) ;
batch ( ( ) => {
batch ( ( ) => {
// Signal is invalidated, but update is not flushed because
// we're still inside another batch
counter . value = 1 ;
} ) ;
// Still not updated...
} ) ;
// Now the callback completed and we'll trigger the effect.
untracked(fn)
如果您收到可以读取一些信号的回调,但您不想订阅它们时,您可以使用untracked
来防止任何订阅发生。
const counter = signal ( 0 ) ;
const effectCount = signal ( 0 ) ;
const fn = ( ) => effectCount . value + 1 ;
effect ( ( ) => {
console . log ( counter . value ) ;
// Whenever this effect is triggered, run `fn` that gives new value
effectCount . value = untracked ( fn ) ;
} ) ;
MIT
,请参阅许可证文件。