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

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

回答

收藏

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

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

本帖最后由 riyad 于 2025-2-23 19:38 编辑
3 e+ ?- E2 Q, l" d0 w- z) N7 l* w9 b1 t( A: P
BrowserNavigator

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


% X% ^6 T7 B% u! [构造函数

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

  1. import { BrowserNavigator } from '@telegram-apps/sdk';
    8 i5 A( q3 Z9 z+ T. y7 t; e  a
  2. + [, C( v0 O1 L" ^+ B5 W
  3. new BrowserNavigator(['/index'], 0);" b; p7 m4 F# c% o7 Z& |
  4. new BrowserNavigator([{ pathname: '/a' }, { pathname: '/b' }], 1);
复制代码

WARNING

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

postEvent

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

  1. const n = new BrowserNavigator(['/'], 0, {
    ' V, C* z, t- |
  2.   postEvent(method, payload) {
    % v! t4 C- @0 m2 p; R3 i4 ?$ Z
  3.     console.log('postEvent:', method, payload);
    + n: v/ l; D! `$ R( L3 _. ?8 I& X0 I
  4.   },$ K" f; b( v- D8 O$ ^3 N" x
  5. });
复制代码
hashMode

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

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

  1. const n = new BrowserNavigator(['/'], 0, {
    % a6 S: j# ~, W% [$ {  w
  2.   hashMode: 'slash'
    3 y* p8 R3 O9 W. j) R
  3. });
复制代码
base

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

  1. const n = new BrowserNavigator(['/'], 0, {
    3 }) }$ j- v0 |& a
  2.   hashMode: null,
    8 l; N' T( S' j( {3 ^5 i! h) {( O
  3.   base: '/solidjs-template',
    ( V# v5 g& e. Y
  4. });
    7 q% K3 V! N' s
  5. + `1 R' u9 j8 ]# h; C+ \
  6. n.renderPath('/home'); // -> /solidjs-template/home
复制代码

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


. `+ \9 q& M/ [5 ~, B0 dcreateBrowserNavigatorFromLocation

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

  1. import { createBrowserNavigatorFromLocation } from '@telegram-apps/sdk';/ E; a* ^* V! V1 F1 Y) f/ _" l
  2. & v; h% [) f$ |4 d$ }5 X9 w
  3. const navigator = createBrowserNavigatorFromLocation({4 Q6 F- M9 e6 Q
  4.   hashMode: 'slash',
    & L( w- Z- J0 l2 R
  5. });
复制代码
initNavigator

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

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

  1. import { initNavigator } from '@telegram-apps/sdk';
    2 x0 R1 E* a$ J* G, ^
  2. / s5 ~. ]7 ~) W2 T" V8 `$ i7 ]
  3. const n = initNavigator('app-navigator-state', {
    ! _3 s$ L/ f* D$ R+ W! c, X6 n' e
  4.   hashMode: 'slash',
    # c# O7 W! k1 e0 w. ?" F
  5. });
复制代码

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


8 p( f+ H, u0 d  E2 }连接

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

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

  1. import { BrowserNavigator } from '@telegram-apps/sdk';9 u6 V# E2 o8 u# g9 R

  2. - ~. ]7 X% u% C! e: f
  3. const navigator = new BrowserNavigator(...);
    6 s! Q( e' s) M! P5 h# L6 o1 K

  4. ' ]; R) t4 w! O8 o) h
  5. navigator.attach().then(() => {
    0 ]8 `, T5 f9 Y0 j  z
  6.   console.log('Attachment completed');% w6 r7 X. s7 m, {4 s- p
  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.& o# J: T. a/ s% ~! m1 e. k1 J7 O1 A
  2. navigator.go(-3);
    8 D' }$ h4 ~- a0 K/ `
  3. ( l$ j% o5 j1 Q- K! d
  4. // Will surely do nothing in real-world applications.
    2 o, G9 H3 ?% c( I1 O
  5. navigator.go(-100000);
    ( @; Q! y6 b/ K+ h+ m

  6. 5 z$ e  U4 s( x9 G  ^
  7. // Will go back to the oldest entry.
    3 u0 `& [+ [. v$ E; Q' b7 g
  8. navigator.go(-100000, true);2 Y+ N  Q) s2 l1 l

  9. 4 h0 C8 s3 s: U8 p9 t) W
  10. // Will go forward to the newest entry.3 B. M% I4 V2 J' ?
  11. navigator.go(100000, true);
复制代码
goTo

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

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

  1. // Will do nothing.
    + _+ L0 W/ _' v6 ^3 G, ^
  2. navigator.goTo(-1);
    ; l+ ?5 f4 ^2 h$ H
  3. + ], o9 f* b  O4 D; d: L' f0 x- T
  4. // Will go to the oldest entry.% `- o, U5 S2 g# n% A7 c/ B
  5. navigator.goTo(0);3 U! P$ ]  S8 w! Z6 f

  6. ) E, h7 H* f+ d$ P. s
  7. // Will surely do nothing in real-world applications.: f( O5 s$ K4 n0 d( O& H
  8. navigator.goTo(100000);2 W3 i2 p* K, d% d
  9. 6 p; T0 Y0 S+ y/ [
  10. // Will go back to the oldest entry.
    4 O% p4 L3 M$ s' F$ k" J- g
  11. navigator.goTo(-100000, true);) D6 V! {  v' _* u) H: [! Z

  12. % X' e0 k) y2 ]: z$ k, N
  13. // Will go forward to the newest entry.
    . O+ F" z! m- j7 Y/ t
  14. navigator.goTo(100000, true);
复制代码
push

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

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

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

绝对路径名

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

  1. navigator.push('/database');2 K% ^% E) {6 e; a% w0 t: h
  2. // or
    , B. M7 n, K3 x  e! b" ^
  3. navigator.push({ pathname: '/database' });/ N# y9 x" N, J0 L: C: Y+ Q0 b
  4. // Navigator will add a new entry, and the current one becomes /database
复制代码
相对路径名

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

  1. navigator.push('license');  O7 u7 ]$ W3 ^
  2. // or$ Q) o$ @8 I2 N5 P% |2 o$ Y
  3. navigator.push({ pathname: 'license' });
    2 N7 k* \% N- _& k
  4. // Navigator will add a new entry, and the current one becomes /home/license
复制代码
搜索

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

  1. navigator.push('?id=1');9 Y% L# r: P  ^5 E
  2. // or
    6 X) z0 S5 @4 u: y
  3. navigator.push({ search: '?id=1' });  C8 n  y& i2 L$ J5 ^8 D/ v
  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');" y$ ^4 q+ n- C0 P$ N
  2. // or
    " R1 f3 l' x0 l% _8 v7 v; ]
  3. navigator.push({ hash: '#introduction' });* ?: @, a3 M; @% J$ f
  4. // Navigator will add a new entry, and the current
    7 g. M# m/ @% A. t, T5 t
  5. // one becomes /home/blog#introduction
复制代码
replace

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

属性index

当前历史光标。

  1. const navigator = new BrowserNavigator(['/'], 0);
    / n/ _" u% r0 ^
  2. navigator.index; // 0
复制代码
id

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

  1. const navigator = new BrowserNavigator(['/'], 0);
    ; C( d  t) q2 C! E6 D- W* @! @  F
  2. navigator.id; // 'abb721'5 I4 j& l) P% ?. w6 r4 x! O4 g. Z

  3. 0 k1 n7 I" J1 ?
  4. const navigator2 = new BrowserNavigator([{ id: 'a', pathname: '/' }], 0);+ L: L. Y8 \  O
  5. navigator2.id; // 'a'
复制代码
hash

当前历史项目哈希值。

  1. const navigator = new BrowserNavigator(['/#jungle'], 0);
    " s: g; h( k/ x+ |$ Z4 j
  2. navigator.hash; // "#jungle"
复制代码
hasPrev

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

  1. const navigator = new BrowserNavigator(['/'], 0);
    # _6 v0 Q( |- h1 m5 d* u8 q
  2. navigator.hasPrev; // false
    5 P0 M) k/ t# e
  3.   |$ Q( p6 P0 _$ t! _3 `
  4. const navigator2 = new BrowserNavigator(['/a', '/b'], 1);
    + U  W/ }- @) s/ {1 z
  5. navigator2.hasPrev; // true
复制代码
hasNext

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

  1. const navigator = new BrowserNavigator(['/'], 0);& c# Q& I+ M4 n& g! G. Y
  2. navigator.hasNext; // false0 e7 ]% m: M& C/ Y5 e6 _0 c" n
  3. 2 \3 O3 E" {  y! N9 N5 t
  4. const navigator2 = new BrowserNavigator(['/a', '/b'], 0);5 B4 M* L* s" F. L9 _7 u4 p; q/ e
  5. navigator2.hasNext; // true
复制代码
history

安全修改导航历史记录。

  1. const navigator = new BrowserNavigator(['/a#a-hash', '/b?b-query=1'], 0);3 j; M9 i( i  u& x  o
  2. navigator.history;
    : r; [0 e7 X5 o! e
  3. // [
    ; ~  w3 d% N6 s# |! [7 }% _
  4. //   { pathname: '/a', hash: '#a-hash', search: '', id: 'ahJJ123' },
    ' `. H8 T7 z8 k# {
  5. //   { pathname: '/b', hash: '', search: '?b-query=1', id: 'dd82' },
    # k1 v' m) K) h0 V& s4 z; ^
  6. // ]
复制代码
path

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

  1. const navigator = new BrowserNavigator([{
    " w) u  W  i6 v  m
  2.   pathname: '/a',- f4 S9 b6 E  d6 ^# g
  3.   hash: '#mama',
    $ N$ Q8 D, b6 e: d
  4.   search: '?joe',
    # G5 P* l0 Q$ k( Y# w
  5. }], 0);
    0 Z' d0 z% A* w
  6. navigator.path; // '/a?joe#mama'
复制代码
pathname

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

  1. const navigator = new BrowserNavigator([{" T7 P+ o* O2 V2 u! w$ X
  2.   pathname: '/a',
      F4 M" C8 a& y$ z$ a& q; w3 ]
  3.   hash: '#mama',; h& r- z$ v- I. l* e
  4.   search: '?joe',7 D! G3 s0 F$ ~* W
  5. }], 0);3 A- t) K' ~; H2 ~6 }5 |4 {
  6. navigator.pathname; // '/a'
复制代码
search

当前查询参数。

  1. const navigator = new BrowserNavigator([{
    ) o5 c' E$ K7 F
  2.   pathname: '/a',
    4 ]! I8 I, U  `
  3.   hash: '#mama',( k7 T- F. b: ~6 z4 N1 T
  4.   search: '?joe',
    ) Z+ o/ k  ^: i* e+ {0 y
  5. }], 0);
    4 n. O3 Q" b7 Y) O0 y0 _
  6. navigator.search; // '?joe'
复制代码

) m" R& S. V6 I# y3 K4 N/ Cstate

当前历史项目状态。

  1. const navigator = new BrowserNavigator([{ state: 'test' }], 0);1 P; n/ s( K% ]1 i. T3 `8 `% S7 S
  2. 7 ]8 H( E! u) b& K2 x

  3. $ W, c& D) ^# M. N
  4. navigator.state; // 'test'
复制代码
2 i! Y' _" l7 i/ o. j' B$ G2 v
事件

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

  • navigator: BrowserNavigator: 相关导航器实例。
  • delta: number: 当前活动项目光标的 delta。
  • from: { pathname: string; hash: string; search: string; id: string; state?状态 }: 以前活动的历史项目。
  • to:结构与 from 相同的对象,代表当前活动的历史项目。
    & \6 \; _6 Q9 l" w& x6 m
$ b4 r1 D. ~  i" K
添加事件监听器

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

  1. const removeEventListener = navigator.on('change', (ev) => {! ?; @: D5 O: p# j6 G
  2.   console.warn('Navigation state changed', ev);. N1 r) c  \% W' m$ l9 y
  3. });
复制代码
删除事件监听器

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

  1. removeEventListener();
复制代码
或者,您也可以使用导航器的 off 方法:
( O& _" P! R; r6 s
  1. function listener(ev) {% c. y2 y% K! {% P! B) w. }
  2.   console.warn('Navigation state changed', ev);8 D9 G- Y; r4 F) I$ V& [& O
  3. }( N0 m0 d* X' N+ H1 s! @; |' e9 V% h
  4. navigator.on('change', listener);
    # J; ?1 @9 v) w+ a. V+ W- X6 \- T
  5. navigator.off('change', listener);
复制代码
其他方法renderPath

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

  1. const n = new BrowserNavigator(['/'], 0, {- u5 j5 u8 G& b; D& K+ C) A
  2.   hashMode: 'slash',# h3 v7 p2 B& `% S7 t2 ?! {
  3. });7 f9 P0 e9 V6 U5 s$ H+ K
  4. n.renderPath('/test'); // '#/test'3 |5 m- T6 i8 D' \3 Z. Y& I

  5. ' d2 x2 b3 O4 T3 m% u' D
  6. const n2 = new BrowserNavigator(['/'], 0, {
    $ e5 [( _/ c9 w5 N+ s* V( S5 [
  7.   base: '/my-base',. r( Y3 I. A2 |* S" C! y# Y3 ]* z1 {
  8.   hashMode: 'slash',5 f2 f5 q4 e* {2 t4 o7 H
  9. });+ X' ^' Z8 w3 K2 x
  10. n2.renderPath('/test'); // '#/my-base/test'
    % ]7 Z! H' _+ F

  11. . n5 N1 c9 H, {- l) w. I
  12. const n3 = new BrowserNavigator(['/'], 0, {$ F+ H6 N5 r- |0 j
  13.   base: '/my-base',/ u: L8 r( ?2 S4 r5 F$ e
  14.   hashMode: null,# J6 l# L8 }( I* T2 M$ k4 K
  15. });
    8 K6 j9 ?  l" h+ b5 U& ]; i0 x! {. x
  16. n3.renderPath('/test'); // '/my-base/test'
复制代码
parsePath

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

" j: B5 j. b5 K* X; C
  1. const n = new BrowserNavigator(['/'], 0);
    4 N' P' W5 \( {3 `) [
  2. n.parsePath('/test');/ N. {; L+ Y! H' x1 m
  3. // { pathname: '/', search: '', hash: '' }
    $ ]* j1 d5 ]1 j' l9 G6 }

  4. 2 z, {$ }( e6 |6 c7 l5 {
  5. n.parsePath('/test#abc');
    8 Z8 @! s8 l. I( d
  6. // { pathname: '/abc', search: '', hash: '' }
    $ `( u2 j' P) g- B5 D

  7. ) c: K2 S& B- |) U
  8. n.parsePath('/test#abc?query#some-hash');
    1 _2 z5 |& v+ U7 s1 i
  9. // { pathname: '/abc', search: '?query', hash: '#some-hash' }
    7 v4 r& `! c% k2 i, K7 E  Y) B
  10. ( X$ |/ ?; ^$ f
  11. const n2 = new BrowserNavigator(['/'], 0, { hashMode: null });1 L3 {+ j) G$ L7 Y5 ?, e( [1 T5 D
  12. n2.parsePath('/test');
    2 `4 ]9 _. i* v- ]" U1 m: Y
  13. // { pathname: '/test', search: '', hash: '' }  C& M  K3 q: ?( ?* w/ w2 Y& ~( T
  14. 0 C+ D1 B6 E# a
  15. n2.parsePath('/test#abc');
    2 @$ L! ^4 y1 \5 P' Y7 }( y. s) n
  16. // { pathname: '/test', search: '', hash: '#abc' }
    8 T! C; o9 I0 E* p- z

  17. 9 _% e+ a( x, U* |5 I
  18. n2.parsePath('/test?query#abc');
    2 b+ f2 b( W& Y+ X1 h2 Q5 }
  19. // { pathname: '/test', search: '?query', hash: '#abc' }
复制代码
+ N: H* f6 c# L, @6 \7 a6 ?
7 u! v/ d, f/ |) M5 w8 d' o

3 _, f7 A, N1 v% A3 W
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则