createSignal
最小 signal:返回 [读, 写],可选地通过共享的 subscribers 总线广播变更,让互不相干的模块也能响应。
API
createSignal(value, options?)
参数
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
value |
初始值 | T |
必填 |
options.subscriber |
事件名;变更时通过 subscribers 广播 |
string |
undefined |
options.equals |
如何判定「算不算变化」 | boolean | ((prev: T, next: T) => boolean) |
true |
equals 语义:
| 取值 | 行为 |
|---|---|
省略 / true |
Object.is,引用/值相等(标准 signal 语义) |
false |
每次写入都算变化并通知 |
| 函数 | 返回 true 表示相等、跳过通知 |
返回
[getter, setter]。
示例
import { createSignal, isEqual, subscribers } from 'ranuts';
const [count, setCount] = createSignal(0, { subscriber: 'count-changed' });
subscribers.tap('count-changed', () => render(count()));
setCount(1); // 触发
setCount(1); // 值相同,不触发
// 确实需要深比较时,显式声明
const [tree, setTree] = createSignal(initial, { equals: isEqual });注意
- 默认引用相等。新构造但深度相等的对象算变化。这符合标准 signal 语义,也让写入保持 O(1)。
- 深比较需显式开启:
{ equals: isEqual },代价明明白白写在调用处。 subscriber可选,不传时就是纯本地状态。
::: warning 0.3 行为变更两处修复会改变行为:
{ equals: true }此前表示「永远相等」,导致 signal 一次也不会更新。现在它表示「用默认比较」,与undefined一致。- 此前每次写入都在
equals之外额外跑一遍cloneDeep+isEqual:既把 O(数据规模) 的拷贝压在写入热路径上,又让这层深比较盖过equals,{ equals: false }(「永远通知」)对深度相等的值静默失效。两者均已移除。 :::