Scott Hanselman 有句名言:URL 是 UI
引言
URL 不仅仅是用户界面的组成部分,它们更是状态容器。URL 能够保存信息、共享信息以及添加信息到书签,为用户和应用提供了强大的数据传递机制。
URL的核心功能
- 🔗 可共享性:向他人发送链接,共享完整的应用状态
- 📌 书签性:保存 URL 为书签,便于后续访问
- 📚 浏览器历史记录:支持前进后退按钮导航
- 🎯 深度链接:跳转到特定的网页状态或内容
URL结构解析
URL 的不同部分对不同类型的状态进行编码,了解其结构对于有效使用至关重要。
Path(路径)
最适合用于分层资源导航:
/users/123/posts- 用户 123 的帖子列表/docs/api/authentication- 文档结构/dashboard/analytics- 应用程序部分
Query(查询参数)
非常适合过滤器、选项和配置:
?theme=dark&lang=en- UI 偏好设置?page=2&limit=20- 分页控制?status=active&sort=date- 数据过滤
Anchor(锚点)
非常适合客户端导航和页面部分:
#L20-L35- GitHub 行高亮#features- 滚动到页面部分#/dashboard- 单页应用程序路由
URL 查询参数使用方式
带分隔符的多个值
?languages=javascript+typescript+python
?tags=frontend,react,hooks
嵌套或结构化数据
?filters=status:active,owner:me,priority:high
?config=eyJyaWNrIjoicm9sbCJ9== (base64-encoded JSON)
标志
?debug=true&analytics=false
?mobile (presence = true)
数组
?tags[]=frontend&tags[]=react&tags[]=hooks
?ids[0]=42&ids[1]=73
例子
// PrismJS 配置
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript&plugins=line-numbers
// GitHub 行高亮
https://github.com/zepouet/Xee-xCode-4.5/blob/master/XeePhotoshopLoader.m#L108-L136
// 谷歌地图
https://www.google.com/maps/@22.443842,-74.220744,19z
// Figma 和设计工具
https://www.figma.com/file/abc123/MyDesign?node-id=123:456&viewport=100,200,0.5
// 电子商务过滤器
https://store.com/laptops?brand=dell+hp&price=500-1500&rating=4&sort=price-asc
前端工程实现
使用原生 JavaScript
现代URLSearchParams API 使 URL 状态管理变得简单明了:
// 读取URL参数
const params = new URLSearchParams(window.location.search);
const view = params.get('view') || 'grid';
const page = parseInt(params.get('page')) || 1;
// 更新URL参数
function updateFilters(filters) {
const params = new URLSearchParams(window.location.search);
params.set('status', filters.status);
params.set('sort', filters.sort);
const newUrl = `${window.location.pathname}?${params.toString()}`;
window.history.pushState({}, '', newUrl);
renderContent(filters);
}
// 处理前进/后退按钮
window.addEventListener('popstate', () => {
const params = new URLSearchParams(window.location.search);
const filters = {
status: params.get('status') || 'all',
sort: params.get('sort') || 'date'
};
renderContent(filters);
});
使用 React 实现
React Router 和 Next.js 提供了专门的钩子:
import { useSearchParams } from 'react-router-dom';
function ProductList() {
const [searchParams, setSearchParams] = useSearchParams();
const color = searchParams.get('color') || 'all';
const sort = searchParams.get('sort') || 'price';
const handleColorChange = (newColor) => {
setSearchParams(prev => {
const params = new URLSearchParams(prev);
params.set('color', newColor);
return params;
});
};
return (
<div>
<select value={color} onChange={e => handleColorChange(e.target.value)}>
<option value="all">所有颜色</option>
<option value="silver">银色</option>
<option value="black">黑色</option>
</select>
</div>
);
}
注意事项
处理默认值
不要使用默认值污染 URL
// 不好的做法:URL变得冗长
?theme=light&lang=en&page=1&sort=date
// 好的做法:只包含非默认值
?theme=dark // light是默认值,所以省略它
在代码中使用默认值读取参数
function getTheme(params) {
return params.get('theme') || 'light';
}
URL 更新防抖
对于高频更新(如搜索输入),对 URL 更改进行防抖处理:
const updateSearchParam = debounce((value) => {
const params = new URLSearchParams(window.location.search);
if (value) {
params.set('q', value);
} else {
params.delete('q');
}
window.history.replaceState({}, '', `?${params.toString()}`);
}, 300);
pushState 与 replaceState
pushState 创建一个新的历史条目,适用于不同的导航操作 (例如更改过滤器、分页或导航到新视图),然后用户可以使用 Back 按钮返回到之前的状态。
replaceState 更新当前条目而不添加新条目,因此非常适合按键入搜索或小的 UI 调整
URL 长度限制
浏览器和服务器对 URL 长度施加了实际限制(通常在 2,000 到 8,000 个字符之间),但现实更加微妙。长度限制来自浏览器行为、服务器配置、CDN 甚至搜索引擎限制的混合。详细解释
数据使用场景
适合通过 URL 传递的数据
- 搜索查询和筛选器
- 分页和排序
- 视图模式(列表/网格、深色/浅色)
- 日期范围和时间段
- 选定项目或活动选项卡
- 影响内容的 UI 配置
- 功能标志和 A/B 测试变体
- 版本控制
- SPA 路径状态
不适合通过 URL 传递的数据
- 敏感信息(密码、令牌、PII)
- 临时 UI 状态(模式打开/关闭,下拉列表展开)
- 正在进行的表单输入(未保存的更改)
- 极大或复杂的嵌套数据
- 高频瞬态(鼠标位置、滚动位置)
判断标准
如果其他人点击这个 URL,他们是否应该看到相同的状态?
- 是 → 适合放入 URL
- 否 → 使用其他状态管理方法
URL 约定规则
清晰的边界
结构良好的 URL 在公共和私有、客户端和服务器、可共享和特定于会话之间划清界限。
语义化
可读的 URL 会自行解释。考虑以下两个 URL 之间的区别。
https://example.com/p?id=x7f2k&v=3
https://example.com/products/laptop?color=silver&sort=price
吉姆·尼尔森 (Jim Nielsen) 优秀 URL 可以解释自己的网址 。
缓存和性能
URL 是缓存键。精心设计的 URL 可实现更好的缓存策略:
- 相同的 URL = 相同的资源 = 缓存命中
- 查询参数定义缓存变体
- CDN 可以根据 URL 模式智能缓存
了解用户操作流程
总结
URL 不仅仅是网络资源的定位符,更是应用状态的重要载体。通过合理使用 URL 的不同部分,我们可以实现状态持久化、用户友好性、SEO 优化、缓存优化和性能提升。
记住:优秀的 URL 本身就是 UI 的一部分,是用户与应用交互的重要媒介。