English 简体中文 繁體中文 한국 사람 日本語 Deutsch русский بالعربية TÜRKÇE português คนไทย french

简体中文 繁體中文 English 日本語 Deutsch 한국 사람 بالعربية TÜRKÇE คนไทย Français русский

回答

收藏

Telegram 小程序 | TypeScript @telegram-apps/signals

开源社区 开源社区 9381 人阅读 | 0 人回复 | 2025-02-20

本帖最后由 riyad 于 2025-2-22 20:09 编辑
7 p2 U6 N+ H9 y' s3 E3 p! e
. ]2 U2 J+ h8 O1 u5 O

我们在整个 @telegram-apps 软件包中使用的 signals 实现。

' w- l+ q  d5 y6 g
安装pnpm 7 A7 n/ M% h- ~3 y9 y
  1. pnpm i @telegram-apps/signals
复制代码
npm
' ^, f/ Z' Z" k/ _- T$ R
  1. npm i @telegram-apps/signals
复制代码
yarn ' {) X0 b% z* u+ N$ ^
  1. yarn add @telegram-apps/signals6 ]4 e0 u* m9 H# j( k' h
复制代码

' j1 o" q" w( T. Z& y
Signal

signal 函数是最简单的 signal 构造函数,被其他软件包函数所使用。 要 创建新 signal,只需传递初始值即可:

  1. import { signal } from '@telegram-apps/signals';
    1 L, r; Z) J! u' [

  2. 7 \; ^. |( I/ s" @
  3. const isVisible = signal(false);
    % S! x9 R( H( T

  4. ; f: Q" ~; i, E% v4 d# d# G# M1 d7 A
复制代码

返回值代表一个具有实用方法的函数。 函数本身返回 当前信号值。

  1. console.log('The element is', isVisible() ? 'visible' : 'invisible');6 {2 \1 C- O# o9 H# E7 q8 ~" J
复制代码

该函数还接受选项作为第二个参数。 开发人员可以指定 equals 函数,该函数接受当前值和输入值,如果认为它们相等,则返回 true, 。


* O& i6 K, g1 H
  1. const s = signal(10, {; q/ q8 ]3 x/ a- |; S
  2.   equals(current, next) {
    - G0 L$ u! s( C/ X3 x
  3.     // Will not update the signal if the next value is) a/ k6 E9 y" C% b7 o: S
  4.     // higher than the current one.. A, e2 |3 \" b) `9 a: N* \0 E
  5.     return next > current;- ~) A; o* v; H
  6.   }6 ]- [# t. c6 d/ }2 w
  7. });
    # g/ C* g4 D, T" c: ]- ]1 K  T6 ~
  8. s.set(20); // will not update the signal3 C8 y* x1 U* p+ z' b
  9. s.set(5); // will update the signal
复制代码
3 V. u! R5 P3 |) o
set1 A- W3 \7 k2 t

要设置新值,请使用 set 方法:

  1. isVisible.set(true);
复制代码
9 |/ W- S$ K- n, [  V
sub) Q3 h3 T" l  I( F

要跟踪信号变化,请使用 sub 方法。 它返回一个函数,用于移除绑定的 监听器。 监听器接受两个参数:当前值和上一个值。

  1. const removeListener = isVisible.sub((current, prev) => {
    5 c0 Q& j2 x& w/ H, f# P
  2.   console.log('Value changed from', prev, 'to', current);: I9 n8 }8 _4 V# a
  3. });4 b  _' s5 n" i

  4. 8 O: a& y8 j' P+ \0 j; N
  5. // Remove the listener whenever needed.! f& y2 k5 E; h( u. _
  6. removeListener();
复制代码

要只调用监听器一次,请使用第二个:

& e; u' i$ h3 v% L6 d- {7 r  d1 k  e
  1. function listener(current: boolean, prev: boolean) {8 m/ t2 H5 r6 i! U6 f4 [
  2.   console.log('Value changed from', prev, 'to', current);
    ' c& j) D- o0 Y% b, F
  3. }
    + @* W4 }9 _- e) M3 ?* B

  4. 0 W& ~- e+ ]% h, d) }" _  ^
  5. isVisible.sub(listener, true);
    8 W9 r: u. x! f/ A" v. K
  6. // or  Y4 W1 J; Q+ s, `8 |$ J6 E3 i
  7. isVisible.sub(listener, { once: true });
复制代码
$ O0 r* F# x/ ?) h; ^
# T! [; ~0 j/ M* t) J! ?- C
unsub
8 r$ ]7 U" o3 v4 G$ n- p) B
+ y% h9 ?& q2 P; c4 H+ m

另外,要移除监听器,开发人员可以使用 unsub 方法:

  1. function listener(current: boolean, prev: boolean) {
    $ ]; {3 b4 D& u6 Q9 R
  2.   console.log('Value changed from', prev, 'to', current);
    / X6 I( \: f" o( K: O
  3. }$ J2 y0 H% ]9 z* t1 \+ y  d5 L

  4. 3 D7 A) K# E& I5 l, Q) M, h
  5. isVisible.sub(listener);7 n2 j  Q5 p' W8 v1 l# F

  6. + @3 w& _2 n. [  K8 o, u( A
  7. // Remove the listener whenever needed.
    ; g* y: k4 p  h
  8. isVisible.unsub(listener);
复制代码

8 l$ G2 L, O; M! {" }$ L# N$ l8 m: {
unsubAll
7 D" X$ ^1 h$ F
$ }+ R7 _& G7 ~% r6 a

要移除所有监听器,请使用 unsubAll 方法:

  1. isVisible.unsubAll();
复制代码

INFO

此方法不会移除计算信号添加的监听器。

$ H. K" A: h8 l$ W# v2 V; e0 r6 v
. y( v! }- o2 J+ h, t# |
reset& a& g5 t4 G$ W9 N: e$ C1 M& T

9 X1 ~$ [0 w) l( r, J

要恢复到最初指定的值,请使用 reset 方法:

  1. import { signal } from '@telegram-apps/signals';3 g# l* _. S0 B
  2. const isVisible = signal(false);2 V2 P5 Y; L6 U  G
  3. isVisible.set(true); // isVisible becomes true
    5 {  [; z/ A# M8 S2 v
  4. isVisible.reset(); // isVisible becomes false again
复制代码
  O0 Y$ E; G# r- H5 }
0 ~% h1 d, _: U/ f$ F
destroy/ g2 f! c. y9 ^- Q$ D( r

7 _0 }  I: h1 ?3 e% l% l( r

当不再需要该信号且该信号没有被任何计算信号监听时,开发者 可以使用 destroy 方法强制移除所有监听者:

  1. isVisible.destroy();
复制代码

% \1 `7 ^; I. p0 {. c5 w
% E. n. ]! A: R1 C, L5 t1 |

: E9 L$ t0 O9 t* X" Q
Computed
8 x/ @4 k% w2 r. Q
$ x6 E& c1 Z/ \5 E# f) W

computed 函数构建了一个计算 signal,当被调用signal的任何 发生变化时,该 signal 会自动重新计算。

这里有一个例子:

  1. import { signal, computed } from '@telegram-apps/signals';1 D* K: w1 h2 p# p5 p$ m' i. B

  2. 9 U- N! z4 e. E5 g# ~/ [
  3. const a = signal(2);
    8 o, c2 E0 y* D% y! d) P
  4. const b = signal(2);5 \4 n7 P% @( i
  5. const sum = computed(() => a() + b()); // 4; W& u& n3 L! v0 P5 E* M  j
  6. ( n) I" b; P% J2 M0 H* o9 G
  7. a.set(5); // sum becomes 7! q- Y( c' |3 A, g
  8. b.set(5); // sum becomes 10
复制代码

返回值代表一个缺少 set 和 reset 方法的信号。

" K6 r; E! U( T: h
批量更改

batch 函数创建一个作用域,在此对 signal 突变进行批处理。

当开发人员希望防止计算 signal 在几个 相关 signal 连续变化时重新计算时,该功能非常有用。

  1. <blockquote><font size="3">import { signal, computed, batch } from '@telegram-apps/signals';1 G  i) w1 N0 s) Q

  2. 8 L( f/ n/ p! ?& L, F
  3. const a = signal(1);
      U, j& y% `/ b2 V9 ], ?
  4. const b = signal(2);, {- h! U; J; h$ m7 h' C
  5. const c = signal(3);
    7 g  I* Z) _+ I) m4 I) ?
  6. const sum = computed(() => a() + b() + c()); // 6- \/ X/ b7 i9 I. M+ K5 ~4 j

  7. 9 g- M) A! ^1 e/ R2 i
  8. // Without batching, re-computation happens 3 times:( H7 f" I( i3 s9 k1 F
  9. a.set(2); // sum recomputes and becomes 7& `# M! d: L6 c4 P5 w
  10. b.set(3); // sum recomputes and becomes 8* i" g, n* Q$ Y, Q1 L, L: N& E
  11. c.set(4); // sum recomputes and becomes 9
    % s. P2 U5 _  N3 C) r5 t

  12. * v% ^5 n& B% W3 T. x- f4 \/ ~
  13. // Reset each signal.' g. O5 l8 N6 M: W) K- O) T& b
  14. a.reset();
    # T6 U+ C, K" q
  15. b.reset();5 v0 I2 K$ l) V$ c" A8 ~! ~$ M
  16. c.reset();
    9 r5 ]. T# I/ ~$ Y) W) F2 H
  17. // Note: reset calls the set method, which also causes
    ( M& _( \4 C$ T: X* q2 W
  18. // the sum signal to recompute.4 M4 _* c0 _* X$ w
  19. ! }4 S% `, k; c/ ?  @
  20. // Now, let's optimize using the batch function:
    1 Y. C; P/ O9 q1 q0 O
  21. batch(() => {( [/ y6 V+ p& b: c3 `* s5 s: y* H5 G
  22.   a.set(2);4 b/ Y/ ~  h# O7 t1 P; B
  23.   b.set(3);! A9 C. ]6 {7 o3 ?- O- d4 [5 t; e
  24.   c.set(4);; ]( U  M$ z, _
  25. });
    ; T& A' ]# V. c: C5 u
  26. // At this point, sum will recompute only once because
    5 ?  t% i" s) P+ a9 O  F
  27. // batch causes the sum signal to wait for the function to complete,
    8 T  c, N% k6 _( f- @7 G/ e
  28. // and then it triggers the recomputation.
    ! X! c) a: d5 m9 |& K
  29. console.log(sum()); // 9</font>
复制代码

7 P) k" G7 J7 f. q; q5 Q7 C
$ |6 I1 r; [( S" u2 y8 v1 T
) r' d: S- h) X% k
: ^: n9 i, b$ s% P/ {3 ~$ o: v

" g* Q2 z. S1 n  P% M0 T
  C1 H. D3 Y3 ^/ q! `0 F6 t
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则