题目与使用场景
站点使用普通链接在同源页面间导航,页面由服务端渲染,不能为了动画改成单页应用。设计目标是在支持 View Transition API 的浏览器中提供连续过渡,在不支持时仍沿用原生导航。回答应覆盖同文档和跨文档两种机制、状态更新失败、历史导航、焦点、滚动位置与减少动画偏好。
面试官考察什么
- 能否区分
document.startViewTransition()的同文档更新和@view-transition触发的跨文档导航。 - 是否理解 API 只是增强层,不能取代链接、历史记录和服务端渲染。
- 是否会用能力检测、失败回退和
prefers-reduced-motion控制风险。 - 是否能验证动画伪元素、焦点管理、慢设备和中断导航。
作答前的澄清问题
先确认导航是否始终同源、是否包含 iframe、是否需要共享元素动画,以及站点是否已有客户端路由。再确认目标浏览器范围、动画时长要求、是否允许只做淡入淡出,以及用户关闭动画后的产品约束。跨文档过渡要求当前页和目标页都选择加入,且浏览器支持该能力;不能把它当作跨域导航方案。
30 秒回答框架
我会保留原生链接和服务端导航,把过渡当作渐进增强。单页局部更新使用能力检测包裹 startViewTransition;多页同源导航在两页声明 @view-transition。更新回调失败时让页面保持可用并记录错误。动画只作用于视图伪元素,遵守减少动画偏好,焦点、滚动和历史语义由正常导航负责。最后用无支持浏览器、回退、前进、慢网和中断场景验收。
分步骤深入解答
- 建立不依赖动画的基线。 链接、表单提交、服务端响应和错误页先独立可用;不要用脚本拦截所有导航来模拟效果。
- 处理同文档更新。 对列表筛选或局部状态变化,检测
document.startViewTransition。支持时在回调中更新 DOM,不支持时直接执行同一更新函数。回调抛错时让调用方显示原有错误状态。 - 处理跨文档导航。 在同源页面的样式中声明
@view-transition { navigation: auto; },由浏览器在导航期间建立过渡;不调用startViewTransition。两页缺一声明或能力不足时,仍走普通导航。 - 控制过渡边界。 只给确实对应的元素设置
view-transition-name,避免重复名称导致快照冲突。使用::view-transition-old与::view-transition-new调整淡入淡出,动画时长保持短且可中断。 - 保护可访问性。
@media (prefers-reduced-motion: reduce)下关闭或缩短动画;导航完成后确认焦点落到新页面的主标题或合理位置,不能依赖截图伪元素传达状态。 - 处理运行时状态。 前进、后退、刷新、网络失败、重复点击和用户离开页面都要有正常结果。过渡只改变视觉时序,不改变 URL、缓存、权限或数据提交语义。
高质量示范回答
我会把实现拆成“原生导航基线”和“可选动画层”。对同文档更新,所有浏览器共用一个 update 函数;支持 API 时调用 document.startViewTransition(update),否则直接调用 update。对服务端渲染的多页导航,在同源页面加入 @view-transition { navigation: auto; },不拦截链接,也不假设跨域可用。
动画只负责视觉连续性。页面结构用稳定的 view-transition-name 标记,默认使用短淡入淡出,减少动画偏好下关闭它。新页面仍通过真实响应完成焦点、滚动和错误处理。测试覆盖不支持 API、回调抛错、后退前进、重复点击、慢 CPU、慢网络、切换标签页和减少动画偏好。依据包括 MDN 的 View Transition API 与 startViewTransition 文档,以及 Chrome for Developers 的跨文档指南。
常见错误
- 把跨文档导航写成调用
startViewTransition;该方法用于同文档,跨文档由导航和 CSS 选择加入。 - 用脚本阻止所有链接,导致键盘、复制链接、后退和无脚本访问退化。
- 假设所有浏览器或 iframe 都支持相同能力,没有能力检测和普通导航回退。
- 为大量元素设置重复名称,或让动画持续太久,造成快照冲突和用户迷失。
- 只测试顺向点击,没有测试失败响应、前进后退、减少动画偏好和动画被中断的情况。
追问及应对
如果同文档更新回调失败怎么办?
把 DOM 更新和错误状态设计成可独立执行的函数。捕获 ViewTransition 的异常只用于记录和收敛动画状态,业务错误仍按原有 UI 展示,不能让动画异常阻断数据更新。
如何验证跨文档过渡没有改变导航语义?
在支持与不支持的浏览器分别检查 URL、历史栈、刷新、复制链接打开、键盘操作、焦点落点和服务端错误页。关闭 CSS 过渡后,页面结果应完全一致。
何时不应该使用共享元素动画?
当元素身份不稳定、列表频繁重排、内容含强烈运动或用户需要立即定位状态时,使用简单淡入淡出或完全关闭动画。视觉收益不足以抵消焦点、性能和理解成本时,应保留原生体验。