您好,登錄后才能下訂單哦!
dojo/framework/src/routing/README.md
commit b682b06ace25eea86d190e56dd81042565b35ed1
Dojo 應用程序的路由
部件(Widget)是 Dojo 應用程序的基本概念,因此 Dojo 路由提供了一組與應用程序中的部件直接集成的組件。這些組件能將部件注冊到路由上,且不需要掌握路由相關的任何知識。Dojo 應用程序中的路由包括以下內容:
Outlet
部件封裝器指定 route 的 outlet key 和表現視圖之間的映射關系Route
配置,用于在路徑和 outlet key 之間建立映射關系Router
基于當前路徑解析 Route
History
提供器負責向 Router
通知路徑的更改Registry
將 Router
注入到部件系統中RouteConfig
用于注冊應用程序的路由,它定義了路由的 path
、關聯的 outlet
以及嵌套的子 RouteConfig
。一個完整的路由就是由遞歸嵌套的 Route 構成的。
路由配置示例:
import { RouteConfig } from '@dojo/framework/routing/interfaces';
const config: RouteConfig[] = [
{
path: 'foo',
outlet: 'root',
children: [
{
path: 'bar',
outlet: 'bar'
},
{
path: 'baz',
outlet: 'baz',
children: [
{
path: 'qux',
outlet: 'qux'
}
]
}
]
}
];
此配置將注冊以下路由和 outlet:
Route | Outlet |
---|---|
/foo |
root |
/foo/bar |
bar |
/foo/baz |
baz |
/foo/baz/qux |
qux |
在 RouteConfig
的 path 屬性中,在 path
的值中使用大括號可定義路徑參數。 Parameters will match any segment and the value of that segment is made available to matching outlets via the mapParams Outlet
options. The parameters provided to child outlets will include any parameters from matching parent routes.
const config = [
{
path: 'foo/{foo}',
outlet: 'foo'
}
];
具有路徑參數的路由,可為每個路由指定默認的參數。當用沒有指定參數的 outlet 生成一個鏈接,或者當前路由中不存在參數時,可使用這些默認參數值。
const config = [
{
path: 'foo/{foo}',
outlet: 'foo',
defaultParams: {
foo: 'bar'
}
}
];
可使用可選的配屬屬性 defaultRoute
來設置默認路由,如果當前路由沒有匹配到已注冊的路由,就使用此路由。
const config = [
{
path: 'foo/{foo}',
outlet: 'foo',
defaultRoute: true
}
];
Router
用于注冊 route 配置,將 route 配置信息傳入 Router 的構造函數即可:
const router = new Router(config);
會自動為 router 注冊一個 HashHistory
歷史管理器(history manager)。可在第二個參數中傳入其他歷史管理器。
import { MemoryHistory } from '@dojo/framework/routing/MemoryHistory';
const router = new Router(config, { HistoryManager: MemoryHistory });
使用應用程序路由配置創建路由后,需要讓應用程序中的所有組件可使用這些路由。這是通過使用 @dojo/framework/widget-core/Registry
中的 Registry
,定義一個將 invalidator
連接到 router 的 nav
事件的注入器,并返回 router
實例實現的。這里使用 key 來定義注入器,路由器的默認 key 值為 router
。
import { Registry } from '@dojo/framework/widget-core/Registry';
import { Injector } from '@dojo/framework/widget-core/Injector';
const registry = new Registry();
// 假設我們有一個可用的 router 實例
registry.defineInjector('router', () => {
router.on('nav', () => invalidator());
return () => router;
};
注意: 路由提供了 注冊 router 的快捷方法。
最后,為了讓應用程序中的所有部件都能使用 registry
,需要將其傳給 vdom renderer
的 .mount()
方法。
const r = renderer(() => v(App, {}));
r.mount({ registry });
路由自帶三個歷史管理器,用于監視和更改導航狀態:HashHistory
、StateHistory
和 MemoryHistory
。默認使用 HashHistory
,但是可在創建 Router
時傳入不同的 HistoryManager
。
const router = new Router(config, { HistoryManager: MemoryHistory });
基于哈希的管理器使用片段標識符(fragment identifier)來存儲導航狀態,是 @dojo/framework/routing
中的默認管理器。
import { Router } from '@dojo/framework/routing/Router';
import { HashHistory } from '@dojo/framework/routing/history/HashHistory';
const router = new Router(config, { HistoryManager: HashHistory });
歷史管理器有 current
、set(path: string)
和 prefix(path: string)
三個API。HashHistory
類假定全局對象是瀏覽器的 window
對象,但可以顯式提供對象。管理器使用 window.location.hash
和 hashchange
事件的事件監聽器。current
訪問器返回當前路徑,不帶 # 前綴。
基于狀態的歷史管理器使用瀏覽器的 history API:pushState()
和 replaceState()
,來添加和修改歷史紀錄。狀態歷史管理器需要服務器端支持才能有效工作。
MemoryHistory
不依賴任何瀏覽器 API,而是保持其自身的內部路徑狀態。不要在生產應用程序中使用它,但在測試路由時卻很有用。
import { Router } from '@dojo/framework/routing/Router';
import { MemoryHistory } from '@dojo/framework/routing/history/MemoryHistory';
const router = new Router(config, { HistoryManager: MemoryHistory });
當每次進入或離開 outlet 時,都會觸發 router
實例的 outlet
事件。outlet 上下文、enter
或 exit
操作都會傳給事件處理函數。
router.on('outlet', ({ outlet, action }) => {
if (action === 'enter') {
if (outlet.id === 'my-outlet') {
// do something, perhaps fetch data or set state
}
}
});
RouterInjector
模塊導出一個幫助函數 registerRouterInjector
,它組合了 Router
實例的實例化,注冊 router 配置信息和為提供的 registry 定義注入器,然后返回 router
實例。
import { Registry } from '@dojo/framework/widget-core/Registry';
import { registerRouterInjector } from '@dojo/framework/routing/RoutingInjector';
const registry = new Registry();
const router = registerRouterInjector(config, registry);
可使用 RouterInjectiorOptions
覆蓋默認值:
import { Registry } from '@dojo/framework/widget-core/Registry';
import { registerRouterInjector } from '@dojo/framework/routing/RoutingInjector';
import { MemoryHistory } from './history/MemoryHistory';
const registry = new Registry();
const history = new MemoryHistory();
const router = registerRouterInjector(config, registry, { history, key: 'custom-router-key' });
路由集成的一個基本概念是 outlet
,它是與注冊的應用程序 route 關聯的唯一標識符。Outlet
是一個標準的 dojo 部件,可在應用程序的任何地方使用。Outlet
部件有一個精簡的 API:
id
: 匹配時執行 renderer
的 outlet 標識。renderer
: 當 outlet 匹配時調用的渲染函數。routerKey
(可選): 在 registry 中定義路由時使用的 key
- 默認為 router
。接收渲染的 outlet 名稱和一個 renderer
函數,當 outlet 匹配時,該函數返回要渲染的 DNode
。
render() {
return v('div', [
w(Outlet, { id: 'my-outlet', renderer: () => {
return w(MyWidget, {});
}})
])
}
可為 renderer
函數傳入 MatchDetails
參數,該參數提供路由專有信息,用于確定要渲染的內容和計算傳入部件的屬性值。
interface MatchDetails {
/**
* Query params from the matching route for the outlet
*/
queryParams: Params;
/**
* Params from the matching route for the outlet
*/
params: Params;
/**
* Match type of the route for the outlet, either `index`, `partial` or `error`
*/
type: MatchType;
/**
* The router instance
*/
router: RouterInterface;
/**
* Function returns true if the outlet match was an `error` type
*/
isError(): boolean;
/**
* Function returns true if the outlet match was an `index` type
*/
isExact(): boolean;
}
render() {
return v('div', [
w(Outlet, { id: 'my-outlet', renderer: (matchDetails: MatchDetails) => {
if (matchDetails.isError()) {
return w(ErrorWidget, {});
}
if (matchDetails.isExact()) {
return w(IndexWidget, { id: matchDetails.params.id });
}
return w(OtherWidget, { id: matchDetails.params.id });
}})
])
}
只要注冊了一個 error
匹配類型,就會自動為匹配的 outlet 添加一個全局 outlet,名為 errorOutlet
。這個 outlet 用于為任何未知的路由渲染一個部件。
render() {
return w(Outlet, {
id: 'errorOutlet',
renderer: (matchDetails: MatchDetails) => {
return w(ErrorWidget, properties);
}
});
}
Link
組件是對 DOM 節點 a
的封裝,允許用戶為創建的鏈接指定一個 outlet
。也可以通過將 isOutlet
屬性值設置為 false
來使用靜態路由。
如果生成的鏈接需要指定在 route 中不存在的路徑或查詢參數,可使用 params
屬性傳入。
import { Link } from '@dojo/framework/routing/Link';
render() {
return v('div', [
w(Link, { to: 'foo', params: { foo: 'bar' }}, [ 'Link Text' ]),
w(Link, { to: '#/static-route', isOutlet: false, [ 'Other Link Text' ])
]);
}
所有標準的 VNodeProperties
都可用于 Link
組件,因為最終是使用 @dojo/framework/widget-core
中的 v()
來創建一個 a
元素。
ActiveLink
組件是對 Link
組件的封裝,如果鏈接處于激活狀態,則可以為 a
節點設置樣式類。
import { ActiveLink } from '@dojo/framework/routing/ActiveLink';
render() {
return v('div', [
w(ActiveLink, { to: 'foo', params: { foo: 'bar' }, activeClasses: [ 'link-active' ]}, [ 'Link Text' ])
]);
}
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。