本帖最后由 riyad 于 2025-2-23 19:38 编辑
) g0 U0 I- P! ]5 ~8 N
: d. \5 d4 Y: WBrowserNavigatorBrowserNavigator 是一个使用浏览器历史 API 实现导航的类。 导航器对标准导航器进行了扩展,提供了基本的导航功能和专门用于 浏览器历史记录的逻辑。 8 ?- h; R0 `7 Q3 U6 ~
构造函数要创建该类的实例,开发人员可以使用该类的构造函数,该构造函数接受历史 项、指向历史项列表条目的光标(索引)以及其他选项: - import { BrowserNavigator } from '@telegram-apps/sdk';# H/ D: ]3 F( o3 x- j9 X
& M4 F. i7 z- f/ m; Z/ T- T- new BrowserNavigator(['/index'], 0);
8 z) ?8 O2 w0 T/ I& b+ }( } - new BrowserNavigator([{ pathname: '/a' }, { pathname: '/b' }], 1);
复制代码WARNING 如果传入的历史项目列表为空,或者游标指向一个不存在的项目, 构造函数将抛出一个适当的错误。 postEventpostEvent 函数允许替换代表 导航器调用 Mini Apps 方法的函数。 - const n = new BrowserNavigator(['/'], 0, {
+ v( h6 O0 d- w - postEvent(method, payload) {
1 E d5 c( |% `6 M% s5 n9 J$ W - console.log('postEvent:', method, payload);. I& Y# g7 m& D }2 @8 S
- },5 L* p* x. g( R! s
- });
复制代码 hashModehashMode 属性允许开发人员设置导航器使用的导航模式。 允许的值有:classic(#pathname)、slash(#/pathname)和null。 传递 null 值 会将导航器从 SPA 模式切换到 MPA 模式,使用整个 href 而不是位置的哈希部分 。 默认情况下,导航器使用 classic 模式。 - const n = new BrowserNavigator(['/'], 0, {( f& H, _& q) ^5 N- y2 T) q
- hashMode: 'slash'$ r" z$ ^- D) ?: {4 I/ E
- });
复制代码 basebase 属性负责解析路由和渲染路径,假定它们必须 以指定的 base 值开始。 - const n = new BrowserNavigator(['/'], 0, {
6 A! ]0 E- ?( [ - hashMode: null,/ t# Z, U4 X q- @7 Z" O" y0 J
- base: '/solidjs-template',
! f$ {% ?1 q/ y$ x+ _9 v - });# k9 O- e$ _+ B7 y4 t6 k
- + x% Z; `4 t/ a* O
- n.renderPath('/home'); // -> /solidjs-template/home
复制代码该值只有在使用 MPA 模式时才有用。 % s; I7 k) a f' O& Z- D! Y( R" }
createBrowserNavigatorFromLocation为了简化创建 BrowserNavigator 的过程,软件包提供了 createBrowserNavigatorFromLocation 方法。 根据所传递的选项(即前面描述的构造函数 选项),它会解析当前位置并创建 一个 BrowserNavigator 实例。 - import { createBrowserNavigatorFromLocation } from '@telegram-apps/sdk';/ C7 H. B0 B8 Z+ O# t
; s+ [% Y# J2 f+ @2 _- const navigator = createBrowserNavigatorFromLocation({
; k6 I4 j# M8 ~3 ?8 z) w* T - hashMode: 'slash',
. A3 `; T$ R) F R0 n - });
复制代码 initNavigatorinitNavigator 函数负责使用先前保存的导航器状态创建一个 BrowserNavigator 实例 。 它还会自动将其保存在会话存储 中,以便将来恢复状态。 该函数接受会话存储密钥名称(其中将包含导航器状态)和 可选对象(代表导航器构造器选项)。 - import { initNavigator } from '@telegram-apps/sdk';
& u- l6 g. F6 d, A( I4 e
; V& ?8 Z3 n, j X1 k+ V- const n = initNavigator('app-navigator-state', {9 @% x9 L0 s8 a
- hashMode: 'slash',
. y9 R9 U. O) j2 l9 D9 b - });
复制代码如果函数无法使用会话存储恢复导航器,它将 使用 createBrowserNavigatorFromLocation 函数。 9 X7 M+ J5 J1 q2 L: {
连接创建 BrowserNavigator 实例并使用其方法不会自动更新 浏览器历史记录。 要做到这一点,开发人员应将其附加到系统中。 在此之前, 导航器只会更新其内部状态,并通知所有订阅者有关更改。 手动 附件是必要的,以防止出现创建多个此类导航器的情况,即 每个导航器都试图用其内部状态控制浏览器历史记录。 为了让导航器控制浏览器的历史记录,需要通过 attach方法来附加历史记录: - import { BrowserNavigator } from '@telegram-apps/sdk';, p( P' j2 V( n4 g' ^" |* X0 X
; x( s' Q6 h' G; S7 l. t- const navigator = new BrowserNavigator(...);; m. m3 a* E: L: Z6 d
- 0 R5 l; t6 R+ }, N
- navigator.attach().then(() => {
* @ I. {1 v( v4 c" u J7 y - console.log('Attachment completed');; {$ c ?6 n3 l' _1 ~; y
- });
复制代码该方法返回一个承诺,当附件完成时,该承诺将被解析。 要阻止导航器修改浏览器的历史记录,请使用 detach 方法: 导航导航器为开发人员提供了一系列操作导航历史记录的方法。 back历史倒退 1. forward历史向前推移 1. go按指定的 delta 值更改当前活动的历史项目索引。 如果更新后的索引指向一个不存在的历史项,该方法不会更改 索引。 在指定 fit 参数之前, 。 如果指定了它,该方法会调整传入的 delta,使 适合[0, history.length - 1]范围。 - // Goes back in history by 3 entries.
# u, ] V/ S0 v- V+ [- O - navigator.go(-3);: K1 [: T# }( ]
: n. h5 v( s' p. b! J1 [- // Will surely do nothing in real-world applications.
: l, ^# e8 I2 N - navigator.go(-100000);
# P" G& y: ~8 ^- f
$ Y/ e; ^) N3 ^6 c9 `- // Will go back to the oldest entry.
5 H. V! Y/ G1 T# l - navigator.go(-100000, true);
- N" a# C' \) _
7 E- F4 E2 A; k8 {- // Will go forward to the newest entry.
) T3 D( O9 Z2 t, U - navigator.go(100000, true);
复制代码 goTo转到指定的索引。 如果传递的索引超出范围,该方法将不起任何作用。 如果指定了 fit 选项,并且索引超出了界限,那么它将被调整为最接近 的界限。 - // Will do nothing.; F+ X# y. b$ o# p6 Q: g
- navigator.goTo(-1);
+ C: P0 x O1 m F6 d8 X, n9 M# U
) W" T8 R; `* ?# U% k- // Will go to the oldest entry.
% p6 L5 ~5 v* q9 w/ J - navigator.goTo(0);/ L5 \2 s1 q+ g
$ e3 f8 w9 a( C5 z7 L- // Will surely do nothing in real-world applications.
! `+ M) W# R8 l7 X - navigator.goTo(100000);2 {# \# W1 p; {4 _9 C; P4 ?+ p
# z0 T' ~1 |6 g" I1 F. ]- // Will go back to the oldest entry.% `* T' q* l7 ^" Y5 o6 G
- navigator.goTo(-100000, true);
0 K+ V* h3 F: { H7 t6 _
5 _" h. O: y) b1 y- // Will go forward to the newest entry.
0 _5 O& c: w+ w - navigator.goTo(100000, true);
复制代码 push推送新的历史项目。 该方法用 推送的条目替换当前条目之后的所有条目。 请注意,传递的项目总是相对的。 如果要将其用作绝对值,请使用 / 前缀。 例如:/absolute, { pathname: '/absolute' }. 要创建最终路径,导航器会使用 URL 类构造函数中的一种方法,根据当前路径解析 路径。 在接下来的示例中,我们假设当前条目为 /home/blog。 绝对路径名指定绝对路径不会将其与当前路径合并,而是使用 的完整路径: - navigator.push('/database');5 M X: F5 Q. q l
- // or5 w$ p( }, S7 S3 Z: _4 V
- navigator.push({ pathname: '/database' });
9 x. c& T7 @. @5 \9 f% @; ` - // Navigator will add a new entry, and the current one becomes /database
复制代码 相对路径名指定相对路径名的行为与浏览器中的行为相同: - navigator.push('license');* {( @, J& M# A' ~, O8 t$ g
- // or" |; Z; [; [. _" U$ {- k
- navigator.push({ pathname: 'license' });
3 E& Y; [" M% H/ L9 t - // Navigator will add a new entry, and the current one becomes /home/license
复制代码 搜索要添加带查询参数的条目,请使用问号 (?) 或 search 条目属性: - navigator.push('?id=1');+ ]. ?* L5 s9 e! H8 V9 s
- // or' M2 ^; r/ G% G" C e G
- navigator.push({ search: '?id=1' });
9 x) f) h/ d* I+ p' d1 E+ E* r - // Navigator will add a new entry, and the current one becomes /home/blog?id=1
复制代码INFO 推送带有不同查询参数或缺少查询参数的新路径名将导致当前 查询参数丢失。 为防止出现这种情况,开发人员应再次通过它们。 Hash添加条目的散列部分的逻辑与 search相同,但使用的是 hashtag (#) 和 hash 条目属性。 - navigator.push('#introduction');
" W$ F! ?3 C. y2 K# m - // or
' f& g7 \9 C2 C9 b" o1 { - navigator.push({ hash: '#introduction' });
- Z/ i+ R; j' s; x+ t6 ~( ~; X - // Navigator will add a new entry, and the current
: S' S# T7 [+ j- H8 m - // one becomes /home/blog#introduction
复制代码 replacereplace 方法的功能与 push 方法类似,但它不会创建新的 条目。 相反,它取代了当前的版本。 属性index当前历史光标。 - const navigator = new BrowserNavigator(['/'], 0);
0 U* B/ t7 r/ y0 v - navigator.index; // 0
复制代码 id当前历史项目标识符。 如果没有明确指定 id,导航器会自行生成。 - const navigator = new BrowserNavigator(['/'], 0);
2 l0 G3 b/ S1 E# v) f( Q5 { - navigator.id; // 'abb721'; h* j# _( d( S' I4 s( \
- % d5 N. u+ _0 G' L1 i3 Y) G1 s" _
- const navigator2 = new BrowserNavigator([{ id: 'a', pathname: '/' }], 0);7 u; v3 Z2 { U( U, ?6 `/ F# B
- navigator2.id; // 'a'
复制代码 hash当前历史项目哈希值。 - const navigator = new BrowserNavigator(['/#jungle'], 0);
1 T( b! X& a6 P8 R D, S - navigator.hash; // "#jungle"
复制代码 hasPrev如果导航器在当前项目之前有项目,则为 True。 - const navigator = new BrowserNavigator(['/'], 0);4 a6 k! u! |# c9 y& q5 W# O
- navigator.hasPrev; // false* a9 a& O. g, C9 ]8 }
- 2 i; J: \9 `2 A5 F
- const navigator2 = new BrowserNavigator(['/a', '/b'], 1);
1 H3 B- \/ d: k9 f5 y' x) _ - navigator2.hasPrev; // true
复制代码 hasNext如果导航器在当前项目之后还有项目,则为 True。 - const navigator = new BrowserNavigator(['/'], 0);
2 Z& i+ j3 d- v6 K' d7 n) \ G - navigator.hasNext; // false
/ n8 Q2 b: O u) O2 w- j
0 M1 b$ U4 R6 J' ~) N- const navigator2 = new BrowserNavigator(['/a', '/b'], 0);0 ^! D9 b+ [! g% D: q& y
- navigator2.hasNext; // true
复制代码 history安全修改导航历史记录。 - const navigator = new BrowserNavigator(['/a#a-hash', '/b?b-query=1'], 0);: [+ f! f9 W# _9 }( t# U8 l
- navigator.history;, w: @* `2 `. \* E$ b; r# ]
- // [
0 g. p, }) R# O' X - // { pathname: '/a', hash: '#a-hash', search: '', id: 'ahJJ123' },
- p# I. E3 T# e" k5 O - // { pathname: '/b', hash: '', search: '?b-query=1', id: 'dd82' },
3 w% i, }/ s- q: ^( N# S - // ]
复制代码 path路径,包括路径名、搜索和哈希值。 - const navigator = new BrowserNavigator([{2 G8 G6 h' A! v% s4 P$ C* D
- pathname: '/a',: s1 U( E% C6 E9 z9 H, a
- hash: '#mama',6 F! |* }5 S; j* x" D" r) A
- search: '?joe',$ V1 V4 o) T! O3 Q, S# q2 y
- }], 0);
/ N6 ~5 U! C: d! l" f6 ]5 O - navigator.path; // '/a?joe#mama'
复制代码 pathname当前路径名。 总是以斜线开头。 - const navigator = new BrowserNavigator([{/ U G4 F" }. f9 e1 j4 M( o8 j
- pathname: '/a',
x4 N* e# G$ z, S0 }7 a - hash: '#mama',
# v5 ^; o" o0 |) t% C Q1 h - search: '?joe',& p* ?2 ]5 k4 E7 H
- }], 0);
# `) E& f$ `2 O. I. L - navigator.pathname; // '/a'
复制代码 search当前查询参数。 - const navigator = new BrowserNavigator([{
7 ]0 ^3 n+ H( d! p+ W+ | ] - pathname: '/a',; Y* ]. Y. f7 }4 \1 e0 B5 {
- hash: '#mama',
0 S9 X+ r& f* l% _2 Y0 Z - search: '?joe',
+ C" M8 w9 k, u* I$ U9 b - }], 0);
" X' Y5 Z, Y. Y% M$ o - navigator.search; // '?joe'
复制代码
- i" c& A+ d" |; g& Dstate当前历史项目状态。 - const navigator = new BrowserNavigator([{ state: 'test' }], 0);
- h" J6 u) J# G9 v - y; J! O$ Y3 k t* p C
. L5 t+ q+ x! d9 X9 A1 W* ~' V- navigator.state; // 'test'
复制代码 7 ~' ~& Z. }9 F, @ x6 t
事件BrowserNavigator 提供了 on 和 off 方法来管理事件监听器。 目前,可用于监听的 事件只有 change。 change 事件的有效载荷是一个对象,包含 以下属性: - navigator: BrowserNavigator: 相关导航器实例。
- delta: number: 当前活动项目光标的 delta。
- from: { pathname: string; hash: string; search: string; id: string; state?状态 }: 以前活动的历史项目。
- to:结构与 from 相同的对象,代表当前活动的历史项目。( e+ i0 q% v( h& m+ c5 A
& U/ [- [0 L h3 T
添加事件监听器要为 change 事件添加事件监听器,请使用 on 方法: - const removeEventListener = navigator.on('change', (ev) => {
, K+ G6 C* Q+ O - console.warn('Navigation state changed', ev);' O2 W3 R3 n, U$ Q, g+ S; b( S
- });
复制代码 删除事件监听器要移除事件监听器,请调用 on 方法返回的函数: 或者,您也可以使用导航器的 off 方法:
3 z! f V9 ]0 @- o5 M& q! w5 U3 |- function listener(ev) {
" x; W1 |- ^" t1 w - console.warn('Navigation state changed', ev);
9 T/ x+ W. J, o5 m; b" u2 h4 V6 S% _ - }
- N. ]3 Q+ v; M! O% X" q2 _ - navigator.on('change', listener);
: l1 B1 E& F5 O6 V# s/ n$ `5 K - navigator.off('change', listener);
复制代码 其他方法renderPathrenderPath 方法将导航器的 base 属性与给定的路径数据相结合,并应用 导航器的导航模式。 该方法以字符串形式返回完全渲染的路径。 - const n = new BrowserNavigator(['/'], 0, {: M n; J" {/ G
- hashMode: 'slash',
* B1 v9 Q2 b( ]5 A% }. V0 W5 {. m3 g - });7 f$ L$ F0 R/ k) e( }
- n.renderPath('/test'); // '#/test'- e, U' i8 f' D0 e% h
5 Z0 u- \( \7 W! W- const n2 = new BrowserNavigator(['/'], 0, {0 d$ q/ V* p% ?$ b3 `5 _; I
- base: '/my-base',' _+ p# l" C1 r/ g% y
- hashMode: 'slash',& g0 p* B6 p h- a" |
- });2 b$ o7 Y2 B, ?2 l t
- n2.renderPath('/test'); // '#/my-base/test'
3 M( d8 D `$ z5 o/ f: b% m1 P - ( e9 r; E& c* N0 K
- const n3 = new BrowserNavigator(['/'], 0, {* F9 _ E% @1 A' @9 }/ {, f! {
- base: '/my-base',
2 C+ B: l0 J5 \3 a7 T! Y - hashMode: null,2 k) c) C9 J; X: q
- });0 W* ^! k% q" [1 N; ^- t- E
- n3.renderPath('/test'); // '/my-base/test'
复制代码 parsePathparsePath 方法会根据当前导航类型解析所提供的路径,并以对象形式返回 。 这种方法有助于了解导航器如何解释给定路径。 ) p: \( E9 \7 V( ~& `) S
- const n = new BrowserNavigator(['/'], 0);
1 E. j! k6 l! x: g - n.parsePath('/test');
( A8 `8 E# V9 K8 Q% c6 [& a/ h0 f6 Q - // { pathname: '/', search: '', hash: '' }
3 c8 p+ ~ g% \ v2 ^2 j& B# ? - 6 U$ k- M' c K% m. K: T! u, l4 D, y1 R
- n.parsePath('/test#abc');
- y' u3 Q7 ^0 y! j9 \9 u - // { pathname: '/abc', search: '', hash: '' }
: i! R) Z) H# {- [2 L& k5 w
4 w L2 g. E# Z" B$ `4 c' L- n.parsePath('/test#abc?query#some-hash');
# o; w1 l$ P% M& B. H& i" ]" r) T - // { pathname: '/abc', search: '?query', hash: '#some-hash' }" s; O4 t, `; x7 \/ ^
- # L' z' h$ l( _ O
- const n2 = new BrowserNavigator(['/'], 0, { hashMode: null });# {: p3 j$ U' |% E" h
- n2.parsePath('/test');
6 E2 O. A: E: F - // { pathname: '/test', search: '', hash: '' }& J9 W/ v- q0 M9 ]0 ?$ ~
$ v8 C! A3 Z/ n% r- n2.parsePath('/test#abc');
- B% @8 Y: X1 r+ v% k3 b/ A - // { pathname: '/test', search: '', hash: '#abc' }- T/ `* v2 b& i* |& U
- 2 w0 |) u0 V3 o: s: x* C) G, @8 L
- n2.parsePath('/test?query#abc');; [$ \1 v2 t* q2 | ~, p7 c
- // { pathname: '/test', search: '?query', hash: '#abc' }
复制代码 # G$ B4 Q) F- P; }4 y
5 H* r5 C0 Q% y5 }0 t
# w5 a) r' W* C+ p5 b4 t% _' W" c0 `$ e |