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

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

回答

收藏

Telegram 小程序 | TypeScript @telegram-apps/sdk @1.x | 导航 | BrowserNavigator

开源社区 开源社区 3140 人阅读 | 0 人回复 | 2025-02-23

本帖最后由 riyad 于 2025-2-23 19:38 编辑 ) f, e  Z& h1 g* W+ B+ w1 M
! m; _* o( }9 d0 \0 q
BrowserNavigator

BrowserNavigator 是一个使用浏览器历史 API 实现导航的类。 导航器对标准导航器进行了扩展,提供了基本的导航功能和专门用于 浏览器历史记录的逻辑。


0 E- u  [  H' H构造函数

要创建该类的实例,开发人员可以使用该类的构造函数,该构造函数接受历史 项、指向历史项列表条目的光标(索引)以及其他选项:

  1. import { BrowserNavigator } from '@telegram-apps/sdk';6 R7 L8 \% }4 i7 h

  2. , l) H7 R2 m# {
  3. new BrowserNavigator(['/index'], 0);
    2 Q8 |3 u% ]0 g) a: s7 p- P
  4. new BrowserNavigator([{ pathname: '/a' }, { pathname: '/b' }], 1);
复制代码

WARNING

如果传入的历史项目列表为空,或者游标指向一个不存在的项目, 构造函数将抛出一个适当的错误。

postEvent

postEvent 函数允许替换代表 导航器调用 Mini Apps 方法的函数。

  1. const n = new BrowserNavigator(['/'], 0, {
    & A" K+ T$ o2 ]3 s
  2.   postEvent(method, payload) {) V- D. v! C# R! S
  3.     console.log('postEvent:', method, payload);
    ' S2 e" S6 W5 R# a$ i
  4.   },$ g+ `6 R6 {$ P
  5. });
复制代码
hashMode

hashMode 属性允许开发人员设置导航器使用的导航模式。 允许的值有:classic(#pathname)、slash(#/pathname)和null。 传递 null 值 会将导航器从 SPA 模式切换到 MPA 模式,使用整个 href 而不是位置的哈希部分 。

默认情况下,导航器使用 classic 模式。

  1. const n = new BrowserNavigator(['/'], 0, {* _, ~8 F) B, m: Q- ]2 ^1 U  f
  2.   hashMode: 'slash'/ G* _) j; l% G" T1 d8 V& Q' i
  3. });
复制代码
base

base 属性负责解析路由和渲染路径,假定它们必须 以指定的 base 值开始。

  1. const n = new BrowserNavigator(['/'], 0, {7 |9 a& I* _7 \5 c
  2.   hashMode: null,
    & `: v7 F* N) j( w5 V: }
  3.   base: '/solidjs-template',
    6 I: u' w+ ^% T4 k+ P
  4. });  B7 d- O& z# _
  5. 7 c0 [5 @$ q$ r: ~0 g
  6. n.renderPath('/home'); // -> /solidjs-template/home
复制代码

该值只有在使用 MPA 模式时才有用。


8 Q: e$ W+ X3 P+ P* W4 k6 ucreateBrowserNavigatorFromLocation

为了简化创建 BrowserNavigator 的过程,软件包提供了 createBrowserNavigatorFromLocation 方法。 根据所传递的选项(即前面描述的构造函数 选项),它会解析当前位置并创建 一个 BrowserNavigator 实例。

  1. import { createBrowserNavigatorFromLocation } from '@telegram-apps/sdk';
    + m* e" `7 `1 T" d4 Q% e4 T

  2. 7 \& ?' u( o9 E  U8 |4 b+ R1 G
  3. const navigator = createBrowserNavigatorFromLocation({  F9 E1 a6 {; y# J, ~( v
  4.   hashMode: 'slash',0 H9 c% W) S- e
  5. });
复制代码
initNavigator

initNavigator 函数负责使用先前保存的导航器状态创建一个 BrowserNavigator 实例 。 它还会自动将其保存在会话存储 中,以便将来恢复状态。

该函数接受会话存储密钥名称(其中将包含导航器状态)和 可选对象(代表导航器构造器选项)。

  1. import { initNavigator } from '@telegram-apps/sdk';
    . r1 |, r1 F/ }  F2 {6 A2 A" L
  2. $ v+ E' B' G, `. t5 @# B: f/ d
  3. const n = initNavigator('app-navigator-state', {/ k: c1 m8 {2 d, v/ A) y3 t
  4.   hashMode: 'slash',6 @) q/ S* g% u+ _% z9 S: R$ S
  5. });
复制代码

如果函数无法使用会话存储恢复导航器,它将 使用 createBrowserNavigatorFromLocation 函数。

  e7 ^2 G3 H; D( F4 b' U0 j
连接

创建 BrowserNavigator 实例并使用其方法不会自动更新 浏览器历史记录。 要做到这一点,开发人员应将其附加到系统中。 在此之前, 导航器只会更新其内部状态,并通知所有订阅者有关更改。 手动 附件是必要的,以防止出现创建多个此类导航器的情况,即 每个导航器都试图用其内部状态控制浏览器历史记录。

为了让导航器控制浏览器的历史记录,需要通过 attach方法来附加历史记录:

  1. import { BrowserNavigator } from '@telegram-apps/sdk';
    ! u' J8 `  M0 p" V" A/ Y- C/ S

  2. / m8 @1 b) k  {1 d2 t
  3. const navigator = new BrowserNavigator(...);$ [  f6 B: z8 b4 o* y3 S
  4. 4 i+ K3 b2 ~. ~4 t# Q9 S; S
  5. navigator.attach().then(() => {
    / c' Y6 x& e( b( @/ F6 D! C
  6.   console.log('Attachment completed');
    0 N. `" K2 G9 T! d
  7. });
复制代码

该方法返回一个承诺,当附件完成时,该承诺将被解析。

要阻止导航器修改浏览器的历史记录,请使用 detach 方法:

  1. navigator.detach();
复制代码
导航

导航器为开发人员提供了一系列操作导航历史记录的方法。

back

历史倒退 1.

  1. navigator.back();
复制代码
forward

历史向前推移 1.

  1. navigator.forward();
复制代码
go

按指定的 delta 值更改当前活动的历史项目索引。 如果更新后的索引指向一个不存在的历史项,该方法不会更改 索引。 在指定 fit 参数之前, 。 如果指定了它,该方法会调整传入的 delta,使 适合[0, history.length - 1]范围。

  1. // Goes back in history by 3 entries.
    7 _* j! L6 U5 G" X9 n* |' j; h: t" t; N
  2. navigator.go(-3);
    * g0 |8 e5 {  H; f( y4 U9 }
  3. , L; k* N  V/ C. `, X$ `
  4. // Will surely do nothing in real-world applications.
    , M3 [8 O9 S& Q4 Y5 c; E
  5. navigator.go(-100000);
    , m- t& i) g6 f. @
  6. 6 T! F$ A/ C/ Q0 \7 p7 s8 {1 P
  7. // Will go back to the oldest entry.2 s. R2 y5 }0 Z2 K- \( r8 t
  8. navigator.go(-100000, true);
    . P+ ~. K) D2 c+ Q' _! e$ z0 E
  9. 7 ?) B% V% c7 D" L0 d  f
  10. // Will go forward to the newest entry.
    3 J/ w( U1 P, W) J$ j4 s
  11. navigator.go(100000, true);
复制代码
goTo

转到指定的索引。 如果传递的索引超出范围,该方法将不起任何作用。

如果指定了 fit 选项,并且索引超出了界限,那么它将被调整为最接近 的界限。

  1. // Will do nothing.
    . a6 D6 U2 s' z7 W1 Y
  2. navigator.goTo(-1);; h( |9 r- _! A" w  P

  3. 1 T( a6 |! B8 o# L! B
  4. // Will go to the oldest entry.
    : K5 Q3 H3 a  ^' D* B" T
  5. navigator.goTo(0);
    * W; [- J" `" l& `# e6 a7 U! B

  6. " p) _" e# s! A0 j
  7. // Will surely do nothing in real-world applications.6 u( \2 h6 h; R9 t# }3 P! P
  8. navigator.goTo(100000);7 C% M3 e5 l* k1 `) N8 [
  9. + Z  k  D6 u4 t- B) z
  10. // Will go back to the oldest entry.
    ( q+ n- }' v: f1 N
  11. navigator.goTo(-100000, true);$ L3 T( y4 K' Z9 @

  12. : J1 i2 }5 c; l0 a) u
  13. // Will go forward to the newest entry.% X6 T* v% _/ V5 K. K  l; w7 w8 U
  14. navigator.goTo(100000, true);
复制代码
push

推送新的历史项目。 该方法用 推送的条目替换当前条目之后的所有条目。 请注意,传递的项目总是相对的。 如果要将其用作绝对值,请使用 / 前缀。 例如:/absolute, { pathname: '/absolute' }.

要创建最终路径,导航器会使用 URL 类构造函数中的一种方法,根据当前路径解析 路径。

在接下来的示例中,我们假设当前条目为 /home/blog。

绝对路径名

指定绝对路径不会将其与当前路径合并,而是使用 的完整路径:

  1. navigator.push('/database');
    + n( Z* r+ K* B- a/ y2 \! f; `
  2. // or8 \; |' R% q  q: |$ i  _
  3. navigator.push({ pathname: '/database' });0 w7 H# X: N/ V& x' j
  4. // Navigator will add a new entry, and the current one becomes /database
复制代码
相对路径名

指定相对路径名的行为与浏览器中的行为相同:

  1. navigator.push('license');% U2 A% E4 p+ m5 }* t7 @
  2. // or+ r8 }3 m6 ]4 e. @, G' ^
  3. navigator.push({ pathname: 'license' });
    4 Y1 j, S, K  S* b/ q; k* M2 P
  4. // Navigator will add a new entry, and the current one becomes /home/license
复制代码
搜索

要添加带查询参数的条目,请使用问号 (?) 或 search 条目属性:

  1. navigator.push('?id=1');
    3 o0 y/ m" c( u1 k. @1 J
  2. // or* F$ h5 D" A. ?' }' n, U. U
  3. navigator.push({ search: '?id=1' });) ^6 _+ M/ i2 ~- V( P' i
  4. // Navigator will add a new entry, and the current one becomes /home/blog?id=1
复制代码

INFO

推送带有不同查询参数或缺少查询参数的新路径名将导致当前 查询参数丢失。 为防止出现这种情况,开发人员应再次通过它们。

Hash

添加条目的散列部分的逻辑与 search相同,但使用的是 hashtag (#) 和 hash 条目属性。

  1. navigator.push('#introduction');
    0 }$ V! K* y/ w7 C5 Z
  2. // or
    + O0 N" E+ Y) `7 j9 {" o8 l; E
  3. navigator.push({ hash: '#introduction' });
    - e5 {& z: A& p, e5 R, I5 z
  4. // Navigator will add a new entry, and the current ; X* W; C2 A$ n" [0 x4 v0 N4 D
  5. // one becomes /home/blog#introduction
复制代码
replace

replace 方法的功能与 push 方法类似,但它不会创建新的 条目。 相反,它取代了当前的版本。

属性index

当前历史光标。

  1. const navigator = new BrowserNavigator(['/'], 0);# J9 a# M; `7 B% B
  2. navigator.index; // 0
复制代码
id

当前历史项目标识符。 如果没有明确指定 id,导航器会自行生成。

  1. const navigator = new BrowserNavigator(['/'], 0);/ b8 R- j7 P, U  g% A7 h
  2. navigator.id; // 'abb721'4 u" U$ N- t3 [1 h2 o/ Z% w" x

  3. / k4 F0 w4 e1 R& Q/ h
  4. const navigator2 = new BrowserNavigator([{ id: 'a', pathname: '/' }], 0);# J# v" W6 A4 \! R6 t
  5. navigator2.id; // 'a'
复制代码
hash

当前历史项目哈希值。

  1. const navigator = new BrowserNavigator(['/#jungle'], 0);8 j) O% Z' q+ {+ W" }- w
  2. navigator.hash; // "#jungle"
复制代码
hasPrev

如果导航器在当前项目之前有项目,则为 True。

  1. const navigator = new BrowserNavigator(['/'], 0);% S+ x$ C+ f! G) t
  2. navigator.hasPrev; // false6 a/ A/ F/ ?6 O3 _
  3. " L. K* j9 Z: P; J4 s% @0 P
  4. const navigator2 = new BrowserNavigator(['/a', '/b'], 1);0 Y& E. A3 ~; f: s2 {; a
  5. navigator2.hasPrev; // true
复制代码
hasNext

如果导航器在当前项目之后还有项目,则为 True。

  1. const navigator = new BrowserNavigator(['/'], 0);
    * ?- m5 u& [# r3 A: m
  2. navigator.hasNext; // false
      N% H' D2 Z6 P

  3. ( o2 z1 n( h: l$ n) k" y# a6 A- K7 @
  4. const navigator2 = new BrowserNavigator(['/a', '/b'], 0);$ K- \9 V- p' J* F3 ]. a  M" k
  5. navigator2.hasNext; // true
复制代码
history

安全修改导航历史记录。

  1. const navigator = new BrowserNavigator(['/a#a-hash', '/b?b-query=1'], 0);. {" F0 l7 R% S# x" T
  2. navigator.history;7 ]% y3 I* W( b/ Q+ }- r5 w4 r2 y
  3. // [
    8 Q, Y9 v: l# M- T6 J/ B
  4. //   { pathname: '/a', hash: '#a-hash', search: '', id: 'ahJJ123' },; w! u: T" h# E: E" n2 Q/ O
  5. //   { pathname: '/b', hash: '', search: '?b-query=1', id: 'dd82' },) |/ ]$ a  a- F
  6. // ]
复制代码
path

路径,包括路径名、搜索和哈希值。

  1. const navigator = new BrowserNavigator([{' S$ [9 I: _' T  x1 s" p% Y/ U' O  L' L
  2.   pathname: '/a',
    1 Y0 u, I4 m, X4 e# p- _
  3.   hash: '#mama',5 H% [, q& W2 B" r- E) q
  4.   search: '?joe',
    , F# z! a) X- J( y
  5. }], 0);
    % Q7 a) U4 q0 L+ ~" x
  6. navigator.path; // '/a?joe#mama'
复制代码
pathname

当前路径名。 总是以斜线开头。

  1. const navigator = new BrowserNavigator([{; p+ c$ L+ b2 P9 O, t
  2.   pathname: '/a'," H) r5 C( J1 u# Z/ @
  3.   hash: '#mama',- a6 j9 D: {7 {' T
  4.   search: '?joe',; |8 F* }5 a0 I0 x( P
  5. }], 0);
    8 n$ O. J, f$ `. Y/ P- `
  6. navigator.pathname; // '/a'
复制代码
search

当前查询参数。

  1. const navigator = new BrowserNavigator([{- ]  x9 w+ [% y: N& Z( K
  2.   pathname: '/a',
      T( J# z$ G3 P+ z
  3.   hash: '#mama',3 l7 j( B. i2 @. B" f
  4.   search: '?joe',
    : p7 c+ c1 _6 S7 T% u8 l
  5. }], 0);' L: F& q$ g. L* |& l  X# o4 K
  6. navigator.search; // '?joe'
复制代码

0 Z$ Q" v( N+ xstate

当前历史项目状态。

  1. const navigator = new BrowserNavigator([{ state: 'test' }], 0);
    $ S0 N: z" O" U7 n6 R
  2. 6 M! h0 j$ b5 H$ o. l% R
  3. ; g7 g- t6 j. M5 ~3 c4 h
  4. navigator.state; // 'test'
复制代码

# e- D" _5 Z3 T$ s4 G$ _: m3 z; Z事件

BrowserNavigator 提供了 on 和 off 方法来管理事件监听器。 目前,可用于监听的 事件只有 change。 change 事件的有效载荷是一个对象,包含 以下属性:

  • navigator: BrowserNavigator: 相关导航器实例。
  • delta: number: 当前活动项目光标的 delta。
  • from: { pathname: string; hash: string; search: string; id: string; state?状态 }: 以前活动的历史项目。
  • to:结构与 from 相同的对象,代表当前活动的历史项目。
    ! q# P0 H( Q2 g: w* m
5 S, s* ]% \# N
添加事件监听器

要为 change 事件添加事件监听器,请使用 on 方法:

  1. const removeEventListener = navigator.on('change', (ev) => {
    % ~7 C! @( K  S
  2.   console.warn('Navigation state changed', ev);8 L6 Q$ A2 Q$ o" f* g/ g+ U
  3. });
复制代码
删除事件监听器

要移除事件监听器,请调用 on 方法返回的函数:

  1. removeEventListener();
复制代码
或者,您也可以使用导航器的 off 方法:1 Z& K- J- `; R/ A0 s/ ~5 a
  1. function listener(ev) {8 G- l/ U$ c+ N$ o' H0 F
  2.   console.warn('Navigation state changed', ev);* B* \, U- v; I
  3. }
    6 p* B9 M7 `# w
  4. navigator.on('change', listener);0 c& d, ^4 O9 C. s
  5. navigator.off('change', listener);
复制代码
其他方法renderPath

renderPath 方法将导航器的 base 属性与给定的路径数据相结合,并应用 导航器的导航模式。 该方法以字符串形式返回完全渲染的路径。

  1. const n = new BrowserNavigator(['/'], 0, {9 W! j9 V( Z0 |: p3 F
  2.   hashMode: 'slash',
    # l* A9 J8 G) K
  3. });
    - B/ @: B5 I1 v9 E4 H) W; g
  4. n.renderPath('/test'); // '#/test'" J" D! P) _% y  q# s8 o+ V6 s4 ^- m

  5. ' H/ m) L, D5 L' k0 J
  6. const n2 = new BrowserNavigator(['/'], 0, {
    5 [% J" A* b( z( H) M% F2 f" y
  7.   base: '/my-base',
    ; A% _. n# i4 y, \
  8.   hashMode: 'slash',
      C4 w7 h, I0 |2 O
  9. });0 U/ [4 c$ T" ?# _0 u! C  H
  10. n2.renderPath('/test'); // '#/my-base/test'
    1 p1 U8 O/ T# l3 a! O- b
  11. ( ^3 h* @. u+ N2 w1 F- J* U
  12. const n3 = new BrowserNavigator(['/'], 0, {
    % I  Y# U8 \5 [& \/ Y3 S
  13.   base: '/my-base',* k7 B- M: l; K5 N. m3 {
  14.   hashMode: null,
    + F) r- [* r% Z
  15. });1 h* G! W+ s9 C* v
  16. n3.renderPath('/test'); // '/my-base/test'
复制代码
parsePath

parsePath 方法会根据当前导航类型解析所提供的路径,并以对象形式返回 。 这种方法有助于了解导航器如何解释给定路径。

, F" C8 U0 u; E1 }
  1. const n = new BrowserNavigator(['/'], 0);
    % H+ ^; h, {  K9 U
  2. n.parsePath('/test');! q: q- w# S5 k6 R' N' `2 q. {
  3. // { pathname: '/', search: '', hash: '' }3 ]- p7 n' n6 t( q& I6 u# n

  4. ) {% i, F0 D- i1 D
  5. n.parsePath('/test#abc');
    # I. {* J8 }5 n- X- P
  6. // { pathname: '/abc', search: '', hash: '' }
    $ d! u) t0 a1 t4 ^
  7. 0 V/ _& r, V1 R% u3 [+ S5 o! T
  8. n.parsePath('/test#abc?query#some-hash');' g0 X9 D7 p' D. [1 F& h
  9. // { pathname: '/abc', search: '?query', hash: '#some-hash' }
    , Y  f3 E& D6 L( Y0 Z" x4 p
  10. 0 @( o/ t" F# a' C& A3 T
  11. const n2 = new BrowserNavigator(['/'], 0, { hashMode: null });
      Z2 s! X+ d3 u9 o- Z1 ~
  12. n2.parsePath('/test');8 X; n6 ]' R6 T  v1 j+ c+ r
  13. // { pathname: '/test', search: '', hash: '' }; \! P) r, u0 S8 ]5 v

  14. 0 `4 J% u5 O# ?& h2 `+ }
  15. n2.parsePath('/test#abc');* T* T# u1 I' v" ~
  16. // { pathname: '/test', search: '', hash: '#abc' }: O1 C. o% o9 h5 w
  17. . s* f# G( V0 t  [2 B; C( m
  18. n2.parsePath('/test?query#abc');
    % y: B% a. H; V% u: r+ ^) d9 I5 j
  19. // { pathname: '/test', search: '?query', hash: '#abc' }
复制代码
% G/ O+ ~3 e1 y
8 S: C& `. K0 G. }2 W
; }$ x3 e/ l* Y( `
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则