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

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

回答

收藏

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

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

本帖最后由 riyad 于 2025-2-23 19:38 编辑
: [% I" ?# }4 ]$ |$ f0 i$ X( p, e8 U2 a2 r
BrowserNavigator

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


! t8 P0 C5 M3 r构造函数

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

  1. import { BrowserNavigator } from '@telegram-apps/sdk';
    8 K" v7 S+ B, @) s( G, S+ t* N) l

  2. # @4 ]3 E) G, B* D/ h4 s- ?
  3. new BrowserNavigator(['/index'], 0);- i4 t. O7 q* t
  4. new BrowserNavigator([{ pathname: '/a' }, { pathname: '/b' }], 1);
复制代码

WARNING

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

postEvent

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

  1. const n = new BrowserNavigator(['/'], 0, {
    , ^/ l/ `# \5 r& ?
  2.   postEvent(method, payload) {
    % T2 _" q- g# h! s/ N
  3.     console.log('postEvent:', method, payload);+ @( S; [* G7 i6 J6 x; F/ X
  4.   },! T. s& Y* F' s: h2 _2 U! R
  5. });
复制代码
hashMode

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

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

  1. const n = new BrowserNavigator(['/'], 0, {
    9 ^4 C# \, N$ m5 K
  2.   hashMode: 'slash', c  t9 \2 a* r# r4 [, Z) i
  3. });
复制代码
base

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

  1. const n = new BrowserNavigator(['/'], 0, {/ V; C, e& _: v- g$ G
  2.   hashMode: null,
    / ?* |7 S, M1 a# S# T
  3.   base: '/solidjs-template',8 i3 q+ i4 B4 y& F  X9 w
  4. });* B: @$ e9 l$ d0 ^
  5. ; I- s/ P7 ~/ L& }3 q
  6. n.renderPath('/home'); // -> /solidjs-template/home
复制代码

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


- H+ P4 G$ v" T* _. rcreateBrowserNavigatorFromLocation

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

  1. import { createBrowserNavigatorFromLocation } from '@telegram-apps/sdk';- C  O7 u/ q) t3 `3 M1 h4 q

  2. 6 t0 K" R+ a' \. h8 Z7 }
  3. const navigator = createBrowserNavigatorFromLocation({( f9 G- `! Y+ b. K- ?* s
  4.   hashMode: 'slash',( D' p7 D( T/ J* z7 [
  5. });
复制代码
initNavigator

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

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

  1. import { initNavigator } from '@telegram-apps/sdk';
      z, h% Z- q, [5 i' ~" h
  2. * {, _, n4 \: R9 m# W- Q, c5 n
  3. const n = initNavigator('app-navigator-state', {! b" A" U* k9 w  p$ B1 v
  4.   hashMode: 'slash',
    / Z2 [: n  D6 `% z4 b% |/ P
  5. });
复制代码

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


, P* t! r' U3 x/ F+ U) K+ q连接

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

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

  1. import { BrowserNavigator } from '@telegram-apps/sdk';' v/ B. o' S0 B" E: a. r* J9 [

  2. ( f7 }1 B$ N7 m5 ]5 t0 D
  3. const navigator = new BrowserNavigator(...);
    6 k: T( ^; d' |0 m
  4.   P/ i. |% r4 H1 p
  5. navigator.attach().then(() => {
    : M: {; H2 q% V4 D" v
  6.   console.log('Attachment completed');. g: b9 ^% c- R' N7 H
  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.
    1 R4 O2 x" O; W8 V  Q6 W+ c5 P% m
  2. navigator.go(-3);
    . X& T5 @9 g! C3 H

  3. 5 Z  W- U! W1 l" l$ Q& F1 u
  4. // Will surely do nothing in real-world applications.
    0 z! \. N8 e& k
  5. navigator.go(-100000);
    ' a  c  R0 C* _/ |
  6. 5 u1 [  s# t4 q. ~2 N. G
  7. // Will go back to the oldest entry.( n  l: {0 l* c6 c
  8. navigator.go(-100000, true);/ g: R/ A7 b: m# P8 `/ b( t6 d

  9. ( b$ X% S% E3 w) `  `
  10. // Will go forward to the newest entry.
    # |$ q2 r8 D+ d! B( b/ n; B( m
  11. navigator.go(100000, true);
复制代码
goTo

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

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

  1. // Will do nothing.
    ; }) B% \. q* o' s- e% k* C  y: e
  2. navigator.goTo(-1);
    * c1 p) W3 _( {/ Y" l: ]# E: A

  3. ) O0 k( P" }( E+ v" }- }; p2 A
  4. // Will go to the oldest entry./ E0 l$ v% S& V; Y6 y; C, M
  5. navigator.goTo(0);, W$ p) t% `. f) `! D
  6. ! O  i. _" C  ]" C6 l5 L& |, ?
  7. // Will surely do nothing in real-world applications.7 \5 @9 p* N% X8 A! U- F, `
  8. navigator.goTo(100000);( I( m  \$ W+ e. e
  9. , ~/ q. E* T( k* z3 _
  10. // Will go back to the oldest entry.7 @: `0 z% {! G9 k/ Q
  11. navigator.goTo(-100000, true);
    6 i0 C: k9 p5 g2 _; K# T

  12. * V! s, _% ?, K3 V/ ^( H) f4 l6 K- ~
  13. // Will go forward to the newest entry.
      i9 R5 x. U" }0 d) c! \" c* |
  14. navigator.goTo(100000, true);
复制代码
push

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

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

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

绝对路径名

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

  1. navigator.push('/database');5 V$ Y% `9 A: x1 F8 ~5 R  ]+ S
  2. // or" ^+ Z+ W$ g5 E9 i2 E  c: M, q
  3. navigator.push({ pathname: '/database' });' f9 b1 O3 R2 [3 b' R9 ^
  4. // Navigator will add a new entry, and the current one becomes /database
复制代码
相对路径名

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

  1. navigator.push('license');
    & t$ m' Y9 q8 U, H3 s# T1 f" J  Y/ c
  2. // or; U& t0 V" b8 k: \' v3 ]
  3. navigator.push({ pathname: 'license' });
    9 a8 j6 U' P; e
  4. // Navigator will add a new entry, and the current one becomes /home/license
复制代码
搜索

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

  1. navigator.push('?id=1');
    4 X5 |6 V/ N& i/ X; W7 J* w" I4 d
  2. // or9 F: y' W5 Y# \* H1 q% B
  3. navigator.push({ search: '?id=1' });0 h1 I( d7 S, S0 W2 R7 E; J8 b
  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');; r( e$ [+ _" B7 z3 |
  2. // or
    " B) O" C; t$ k# E1 u: u
  3. navigator.push({ hash: '#introduction' });
    ; i" t8 r& _- o
  4. // Navigator will add a new entry, and the current 8 A3 L) ]$ c2 @3 K- z& d
  5. // one becomes /home/blog#introduction
复制代码
replace

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

属性index

当前历史光标。

  1. const navigator = new BrowserNavigator(['/'], 0);
    ( ]# J3 X7 t( |( v6 i& P3 ]
  2. navigator.index; // 0
复制代码
id

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

  1. const navigator = new BrowserNavigator(['/'], 0);
    $ ]8 x$ L; i5 M3 j- ^
  2. navigator.id; // 'abb721'! h  f7 }* u# u( ^+ a& o, z
  3. . ^  W' O+ r# T3 o5 }; d
  4. const navigator2 = new BrowserNavigator([{ id: 'a', pathname: '/' }], 0);5 m6 \- c6 x$ V( M% e2 x1 A% i' M8 @
  5. navigator2.id; // 'a'
复制代码
hash

当前历史项目哈希值。

  1. const navigator = new BrowserNavigator(['/#jungle'], 0);
    - f8 l7 P$ b* ]3 }
  2. navigator.hash; // "#jungle"
复制代码
hasPrev

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

  1. const navigator = new BrowserNavigator(['/'], 0);
      R0 @; N  w6 t" E
  2. navigator.hasPrev; // false+ u0 H( n# i* G7 w8 ?

  3. ) o5 P' }, K5 r5 \  R
  4. const navigator2 = new BrowserNavigator(['/a', '/b'], 1);
    1 [  g- f& x  O5 L  `' d  i
  5. navigator2.hasPrev; // true
复制代码
hasNext

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

  1. const navigator = new BrowserNavigator(['/'], 0);4 E! _- ]: E+ i0 Z" y
  2. navigator.hasNext; // false
    3 Q6 b/ o; y3 O% V3 J: M
  3. : g2 e1 V$ f; c
  4. const navigator2 = new BrowserNavigator(['/a', '/b'], 0);/ u% Y& e/ M+ j( V
  5. navigator2.hasNext; // true
复制代码
history

安全修改导航历史记录。

  1. const navigator = new BrowserNavigator(['/a#a-hash', '/b?b-query=1'], 0);$ a6 T" p0 ?6 `! {
  2. navigator.history;
    # R: R& |  A0 f. n* \: l7 `* Y
  3. // [: c7 g0 y7 l/ H5 j
  4. //   { pathname: '/a', hash: '#a-hash', search: '', id: 'ahJJ123' },
    % Y) Z. N  A* c3 q5 I  s
  5. //   { pathname: '/b', hash: '', search: '?b-query=1', id: 'dd82' },4 e" ~7 S5 g# Y% z' B2 p: b& R( ?
  6. // ]
复制代码
path

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

  1. const navigator = new BrowserNavigator([{
    % w! _8 `/ ]2 T5 h0 X2 b
  2.   pathname: '/a',5 @' m0 z! i. V: P
  3.   hash: '#mama',
    % v, C* D) [/ I3 L: m) o
  4.   search: '?joe',
    + ]& P0 d0 @4 \1 l3 y" v
  5. }], 0);' h: M) O, B% F
  6. navigator.path; // '/a?joe#mama'
复制代码
pathname

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

  1. const navigator = new BrowserNavigator([{
    ( N3 P+ I# }! h" i! f0 E8 P) |
  2.   pathname: '/a',
      |* F# d& U# j; m+ Q& ~% t% E' C
  3.   hash: '#mama',
    " E$ j" k" F5 [/ y4 ~' W$ y! o3 v. V
  4.   search: '?joe',
    6 ?4 a: S' {4 @- p6 C) @
  5. }], 0);
    6 x! R& x; o6 D, S7 U  m, n
  6. navigator.pathname; // '/a'
复制代码
search

当前查询参数。

  1. const navigator = new BrowserNavigator([{
    / D! D( Y5 {% q+ b4 `
  2.   pathname: '/a',
    6 s: r& M0 e+ M/ Q' B
  3.   hash: '#mama',
      H1 Y& @( ?, j1 u" P, ^
  4.   search: '?joe',: @5 V; V; F, l/ w0 M4 E5 s
  5. }], 0);% f, m: C. j+ e  x8 Y6 B
  6. navigator.search; // '?joe'
复制代码
) E! P+ k7 a2 U% m+ C0 l
state

当前历史项目状态。

  1. const navigator = new BrowserNavigator([{ state: 'test' }], 0);
    . P6 Q) |/ P0 W3 z% e
  2. ( ]! d2 E# c/ \

  3. 7 q& ~6 w0 V8 |% M4 D
  4. navigator.state; // 'test'
复制代码

7 i6 ?1 _4 R2 F9 {5 S  X9 `( N# U  k事件

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

  • navigator: BrowserNavigator: 相关导航器实例。
  • delta: number: 当前活动项目光标的 delta。
  • from: { pathname: string; hash: string; search: string; id: string; state?状态 }: 以前活动的历史项目。
  • to:结构与 from 相同的对象,代表当前活动的历史项目。- R" M. X. e* J. v: G
( @, G8 I, A. r( v2 |7 ]' ]9 p8 I
添加事件监听器

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

  1. const removeEventListener = navigator.on('change', (ev) => {
    0 X4 w8 _' y; @1 O6 c) K7 g
  2.   console.warn('Navigation state changed', ev);. w8 _, o2 v7 M0 i
  3. });
复制代码
删除事件监听器

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

  1. removeEventListener();
复制代码
或者,您也可以使用导航器的 off 方法:
6 }9 y0 q% `4 X: f" b' |
  1. function listener(ev) {
    " u6 d/ @* Y# S  |9 r
  2.   console.warn('Navigation state changed', ev);
    ( U( C" A- I$ }3 c* h
  3. }
    % N8 N6 \% v( `. F4 O1 `, ]6 z
  4. navigator.on('change', listener);$ \8 v7 x' W2 @
  5. navigator.off('change', listener);
复制代码
其他方法renderPath

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

  1. const n = new BrowserNavigator(['/'], 0, {4 S9 Q3 i5 N: A/ D' _
  2.   hashMode: 'slash',1 t: o( t0 V$ N% A1 W# [$ D
  3. });  a" x' Q. t/ w9 j# ^
  4. n.renderPath('/test'); // '#/test'
    : r* q) D0 `) a* |; M6 D
  5. ! P1 `) i+ h; u& B4 r+ T# t
  6. const n2 = new BrowserNavigator(['/'], 0, {
    ' G/ k; r5 N" _- ]4 ^
  7.   base: '/my-base',
    1 Z5 I3 s0 e! \4 B1 v; ?& Q
  8.   hashMode: 'slash',
    3 a( j% b+ T; a/ m; G7 v
  9. });
    % K! Y) e# G7 C2 g7 n. F3 O
  10. n2.renderPath('/test'); // '#/my-base/test'! K  `- I9 ?" w+ I

  11. , w0 E+ l; a: I; n* Z/ M6 {( Y
  12. const n3 = new BrowserNavigator(['/'], 0, {
    % h: S; {. w2 X' t7 z9 I, T
  13.   base: '/my-base',
    & O1 @* v) [/ V$ Q- b4 k8 W
  14.   hashMode: null,
    3 `4 A7 {6 U; m0 J  ]+ ~# B9 A
  15. });; t3 K' O3 }5 m7 D8 X
  16. n3.renderPath('/test'); // '/my-base/test'
复制代码
parsePath

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

2 n! q, U: B( O$ J9 J+ V0 d1 W
  1. const n = new BrowserNavigator(['/'], 0);8 k8 V  N6 z5 g# @. x
  2. n.parsePath('/test');' w  ~1 g4 u3 v, h& v5 D) ^
  3. // { pathname: '/', search: '', hash: '' }
    8 Z5 e% W( s8 d9 e8 J' Y' r

  4. ( }, \, M5 Y+ {9 ^9 u' c
  5. n.parsePath('/test#abc');
    9 l# H2 n4 A% B
  6. // { pathname: '/abc', search: '', hash: '' }& @* N& e) Y! X* P+ T4 D! r
  7. 4 X# S5 e, P- g7 r  }( f* O; K
  8. n.parsePath('/test#abc?query#some-hash');. k! T- ~; M/ h% _
  9. // { pathname: '/abc', search: '?query', hash: '#some-hash' }
    4 P: c$ Q5 w3 V; h. w+ [

  10. / a. w& R+ y8 ]. T
  11. const n2 = new BrowserNavigator(['/'], 0, { hashMode: null });
    $ M& K  }* w6 e5 a9 Y  Z' v) m4 V9 W
  12. n2.parsePath('/test');) g7 k  V$ b8 E4 Y  P3 \  s- h4 W3 Z
  13. // { pathname: '/test', search: '', hash: '' }' A9 ?0 y1 m  R$ }& Z4 p- W
  14. 1 H) j( N7 q7 }9 M0 h* F
  15. n2.parsePath('/test#abc');1 \1 C, O# m, C
  16. // { pathname: '/test', search: '', hash: '#abc' }
    4 j: p( c, v1 [6 b1 e1 k+ U
  17. ) ^; j: `; y* I4 S3 Z$ H0 u3 x
  18. n2.parsePath('/test?query#abc');  q4 h8 m5 l  W8 _
  19. // { pathname: '/test', search: '?query', hash: '#abc' }
复制代码

% v. L, n# O) ?+ z2 S4 s8 S: O2 s
4 v1 f+ f3 H2 o, p% O. B' j: U, a0 U3 _" H) D
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则