@dasch-ng/路由信号
以路由参数,查询参数,和路由数据作为信号工作的角功用,再将信号写回查询参数.
特征
- 🎯 类型安全信号 - 获得完整类型脚本支持的路由状态
- 🔄 自动更新 - 路由改变时更新信号
- 🔐 URL 解码 - 自动解码URL编码值
- 🛡️ 处理错误 - 错误的URL的安全解码与倒置
- ⚡ 零依赖关系 - 只能靠角和RxJS来
- 📦 树能震动 - 只导入你需要的东西
安装
npm install @dasch-ng/route-signals
使用量
路线参数
作为信号跟踪 URL 路径参数 :
import { Component } from '@angular/core';
import { routeParam } from '@dasch-ng/route-signals';
@Component({
selector: 'app-user-detail',
template: `
<h1>User: {{ userId() }}</h1>
<p>Group: {{ groupId() }}</p>
`,
})
export class UserDetailComponent {
// Route: /users/:userId/groups/:groupId
readonly userId = routeParam('userId');
readonly groupId = routeParam('groupId');
constructor() {
// URL: /users/john-doe/groups/admin
console.log(this.userId()); // "john-doe"
console.log(this.groupId()); // "admin"
// Automatically decodes URL-encoded values
// URL: /users/john%20doe/groups/team%20alpha
console.log(this.userId()); // "john doe"
console.log(this.groupId()); // "team alpha"
}
}
查询参数
作为信号跟踪 URL 查询参数 :
import { Component } from '@angular/core';
import { routeQueryParam } from '@dasch-ng/route-signals';
@Component({
selector: 'app-search',
template: `
<h1>Search: {{ query() }}</h1>
<p>Filter: {{ filter() }}</p>
<p>Sort: {{ sort() }}</p>
`,
})
export class SearchComponent {
// URL: /search?q=angular&filter=tutorials&sort=recent
readonly query = routeQueryParam('q');
readonly filter = routeQueryParam('filter');
readonly sort = routeQueryParam('sort');
constructor() {
console.log(this.query()); // "angular"
console.log(this.filter()); // "tutorials"
console.log(this.sort()); // "recent"
// Automatically decodes URL-encoded values
// URL: /search?q=angular%20signals&filter=a%2Fb
console.log(this.query()); // "angular signals"
console.log(this.filter()); // "a/b"
}
}
路由数据
作为信号的跟踪路由数据属性 :
import { Component } from '@angular/core';
import { routeData } from '@dasch-ng/route-signals';
// In route configuration:
const routes = [
{
path: 'admin',
component: AdminComponent,
data: { title: 'Admin Dashboard', role: 'admin' },
},
];
@Component({
selector: 'app-admin',
template: `
<h1>{{ title() }}</h1>
<p>Required role: {{ role() }}</p>
`,
})
export class AdminComponent {
readonly title = routeData<string>('title');
readonly role = routeData<string>('role');
constructor() {
console.log(this.title()); // "Admin Dashboard"
console.log(this.role()); // "admin"
}
}
有解析器
路由数据与角解器无缝:
import { inject } from '@angular/core';
import { ActivatedRouteSnapshot } from '@angular/router';
import { UserService } from './user.service';
// Resolver
const userResolver = (route: ActivatedRouteSnapshot) => {
const userService = inject(UserService);
const userId = route.paramMap.get('id');
return userService.getUser(userId);
};
// Route configuration
const routes = [
{
path: 'user/:id',
component: UserDetailComponent,
resolve: { user: userResolver },
// Re-run resolver when params change
runGuardsAndResolvers: 'paramsChange',
},
];
// Component
@Component({
selector: 'app-user-detail',
template: `
<h1>{{ user().name }}</h1>
<p>{{ user().email }}</p>
`,
})
export class UserDetailComponent {
readonly user = routeData<User>('user');
// Signal automatically updates when resolver re-runs
}
API 密码
routeParam(key: string): Signal<string>
创建跟踪 URL 编码路由参数的信号.
- 参数:
key: 要跟踪的路由参数名称
- 回返情况: 包含已解码参数值的信号
- 掷出 : 参数在当前路由中没有时出错
routeQueryParam(key: string): Signal<string>
创建跟踪 URL 编码查询参数的信号.
- 参数:
key: 要跟踪的查询参数的名称
- 回返情况: 包含已解码的查询参数值的信号
- 掷出 : 如果当前路由中没有查询参数, 错误
routeData<T>(key: string): Signal<T>
创建跟踪路径数据属性的信号.
- 类型参数:
T: 数据属性的类型
- 参数:
key: 要跟踪的数据属性名称
- 回返情况: 包含路由数据值的信号
- 掷出 : 在当前路由中没有数据属性时出错
bindQuerySignal<T>(options: BindQuerySignalOptions<T>): void
写入 a WritableSignal 输入查询参数。 此信号在创建时从 URL 设定一次; 之后更改更新 URL( debunted, replaceUrl页:1 序列化的值 defaultValue 删除参数.
- 选项 :
signal, (中文(简体) ),param, (中文(简体) ),defaultValue选项serialize(value) => string | null财务报告和审定财务报表deserialize(raw) => T - URL只在创建时被读取. 与
routeQueryParam以跟踪后向导航.
export class AssetListComponent {
readonly search = signal('');
readonly size = signal<MinMaxRange | null>(null);
constructor() {
bindQuerySignal({ signal: this.search, param: 'q', defaultValue: '' });
bindQuerySignal({
signal: this.size,
param: 'size',
defaultValue: null,
serialize: serializeMinMaxRange,
deserialize: deserializeMinMaxRange,
});
}
}
查询参数解码器
现成 serialize编号 :deserialize 用于 bindQuerySignal数字 :
serializeMinMaxRange编号 :deserializeMinMaxRange数字 :{ min: 5, max: 100 }⇄5-100(开口:5-, (中文(简体) ),-100(中文(简体) )serializeDateRange编号 :deserializeDateRange数字 :{ start, end }⇄2026-01-01,2026-02-15(当地日历日期)
URL 解码
所有函数使用安全解码器自动解码 URL-编码值:
- 解码标准 URL 编码( 例如 ),
%20• 空间) - 处理特殊字符(例如,
%2F→/, (中文(简体) ),%3D→=(中文(简体) ) - 解码Unicode字符(例如,
%E2%9C%93→✓(中文(简体) ) - 安全处理错误的编码( 日志警告并返回原始字符串)
处理错误
如果请求的参数/数据不在路由中, 所有函数都会丢出错误 。 这有助于早期抓取配置错误 :
// If route doesn't have an 'id' parameter
const userId = routeParam('id'); // ❌ Throws: "id is not in route."
// If route doesn't have a 'search' query parameter
const search = routeQueryParam('search'); // ❌ Throws: "Query parameter "search" is not in route."
// If route data doesn't have a 'title' property
const title = routeData('title'); // ❌ Throws: "Route data property "title" is not in route."
所需资源
- 角数 19.0.0以上
- RxJS 7.5.0或以上
许可证
麻省理工学院 丹尼尔·舒巴