1. 引言
现代 Web 应用程序常常会响应用户交互来动态更新内容,而不会 执行完整的页面导航。这些由交互发起的效果——例如结构性 DOM 修改、内容绘制以及历史状态变更——长期以来都难以 测量,并难以归因到正确的用户操作。
考虑一种典型的单页应用程序模式:用户点击一个产品链接,这会触发一个
click 事件处理器。该处理器发起一次网络 fetch
来获取产品详情。当
响应到达时,会执行一个回调,将新内容动态注入 DOM,并
使用 History 或 Navigation API 来更新 URL。虽然这在用户看来像是一次
导航,但 Largest Contentful Paint(LCP)等现有指标([LARGEST-CONTENTFUL-PAINT])只
测量初始页面加载,而 Interaction to Next Paint(INP)只测量点击本身的即时
视觉反馈,导致后续显著的渲染以及“软”
导航没有被捕获。
本规范利用 [EVENT-TIMING] API 来定义交互,并利用 [ASYNC-CONTEXT] 提案跨异步任务边界跟踪因果关系,将被修改的 DOM 节点映射到交互,从而能够把内容绘制归因到导致这些绘制的交互。 本规范定义浏览器如何识别并报告这些效果,包括“软导航”, 通过与 [PAINT-TIMING] 和 [LARGEST-CONTENTFUL-PAINT] 集成,将渲染变化 归因到性能时间线。
2. 性能时间线切片
为了将性能指标(例如事件计时、布局偏移、资源加载或长动画帧)归因到触发它们的导航,
性能时间线会使用 navigationId
属性在 PerformanceEntry
上被切分为多个片段。
确定一个跨越时间的转换的确切切分点是复杂的。为确保归因一致, 本规范采用一种模型:时间线不会在每次 URL 修改时立即切分;相反,该转换会被推迟到 软导航 准备好被发送到性能时间线时。
有关设计权衡、归因规则和边界情况的详细讨论,参见 [PERFORMANCE-TIMELINE] issue comment。
2.1. 导航 ID
navigation id 是一个唯一 标识符,分配给 global object 生命周期内的每次导航(包括硬导航和 软导航)。
每个 Window
都具有:
-
一个 current navigation id,一个 64-bit unsigned integer, 初始设置为该
Window的 initial navigation id value。 -
一个 navigation count,一个 64-bit unsigned integer,初始为 0。
-
一个 initial navigation id value,一个 64-bit unsigned integer, 初始设置为 100 到 10000 之间的一个随机整数。
-
一个 navigation id increment,一个 64-bit unsigned integer, 初始设置为由用户代理选择的一个小的正整数。
注: initial
navigation id value 和 navigation id increment 用于计算
navigationId
值(参见
increment the current navigation id)。
这会阻止开发者依赖它来计算确切的导航次数,或
假定它从零开始。
用户代理应避免在不同的 Window
对象之间使用共享的全局导航值,以防止跨源泄露。
Window
window,要 increment the current navigation id:
-
将 window 的 navigation count 设置为 window 的 navigation count 加 1。
-
令 newId 为 window 的 initial navigation id value 加上 (window 的 navigation count 乘以 window 的 navigation id increment)。
-
将 window 的 current navigation id 设置为 newId。
2.2. PerformanceEntry 扩展
[Exposed =(Window ,Worker )]partial interface PerformanceEntry {readonly attribute unsigned long long ; };navigationId
PerformanceEntry
都有关联的 navigation id,
一个 64-bit unsigned integer,初始为 0。
navigationId
属性的 getter 必须返回 this 的 navigation id。
2.3. 性能时间线集成
在 queue a PerformanceEntry 中,在步骤 1(初始化 entry)之后,添加以下步骤:
-
如果 newEntry 的 navigation id 为 0:
-
如果 global 是一个
Window对象:-
将 newEntry 的 navigation id 设置为 global 的 current navigation id。
-
-
3. 交互基础设施
3.1. 交互上下文简介
本规范利用 TC39 [ASYNC-CONTEXT] 提案来处理这种传播。每个
新的用户交互(由 Event Timing 定义)或相关的导航事件都会创建一个新的
InteractionContext。该上下文存储在一个隐藏的、仅供内部使用的 AsyncContext
(表示为 )中。
Web 平台与 AsyncContext 的集成确保该变量会自动
附加到异步延续(例如 setTimeout、fetch、)上,使
浏览器
能够将后续影响归因回原始交互。
除了脚本传播之外,本规范还定义了修改 DOM 的用户交互如何建立一组与该交互关联的已修改 节点, 从而允许后续渲染效果(例如内容绘制)即使在当前没有异步脚本正在 运行时,也能追溯到发起该交互的上下文。
3.2. InteractionContext 结构
-
id,一个64 位无符号整数,表示与此上下文关联的
interactionId。 -
context document,一个 Document。
-
start time,一个数。
-
navigation type,一个
NavigationType或 null,初始值为 null。 -
first URL value,一个字符串或 null,初始值为 null。
-
first URL update timestamp,一个 数,初始值为 0。
-
first scroll timestamp,一个数, 初始值为 0。
-
first input timestamp,一个数, 初始值为 0。
-
first contentful paint,一个
InteractionContentfulPaint或 null,初始值为 null。 -
largest contentful paint,一个
InteractionContentfulPaint或 null,初始值为 null。 -
current largest contentful paint candidate,一个最大内容绘制候选 或 null,初始值为 null。
-
last URL value,一个字符串或 null,初始值为 null。
-
emitted,一个布尔值,初始值为 false。
注: 本规范的未来版本可能会跟踪
在一个交互上下文中发生的所有 URL 更新,以提供更完整的导航历史。last URL
value 会被
内部跟踪,以确保即使当前仅在
PerformanceSoftNavigation
的
name 中公开 first URL value,仍能将影响准确归因回
交互的最终状态。
3.3. 基础设施算法
-
令 context 为内部
AsyncContext. Variable的值。[[ ActiveInteractionContext]] -
如果 context 不为 null,且 context 的上下文文档不等于 document,则返回 null。
-
返回 context。
PerformanceEventTiming
timing entry 的情况下获取或创建某次交互的上下文:
-
令 interaction id 为 timing entry 的
interactionId。 -
断言 interaction id 大于 0。
-
如果 document 的交互 id 到交互 上下文[interaction id] 存在, 则返回 document 的交互 id 到交互 上下文[interaction id]。
-
令 interaction context 为一个新的 InteractionContext。
-
将 interaction context 的 id 设置为 interaction id。
-
将 interaction context 的上下文文档设置为 document。
-
设置 document 的交互 id 到交互 上下文[interaction id] 为 interaction context。
-
返回 interaction context。
-
如果 event 的类型为 "scroll",则令 is scroll 为 true;否则为 false。
-
如果 event 的类型是会触发 已派发输入事件的事件类型(如 [EVENT-TIMING] 中定义),则令 is input 为 true;否则为 false。
-
如果 is scroll 为 false 且 is input 为 false,则返回。
-
对于 document 的交互 id 到交互 上下文的 values 中的每个 interaction context:
PerformanceEventTiming
对象 timing entry 的情况下设置用于
事件派发的当前交互上下文:
-
如果 timing entry 为 null,则返回 null。
-
令 interaction id 为 timing entry 的
interactionId。 -
如果 interaction id 为 0,则返回 null。
-
令 event 为 timing entry 的关联事件。
-
令 document 为 event 的相关全局对象的关联 Document。
-
在给定 document 和 event 的情况下,更新某个事件的交互上下文。
-
令 interaction context 为在给定 document 和 timing entry 的情况下获取或创建某次交互的上下文的结果。
-
将内部
AsyncContext. Variable的值设置为 interaction context。[[ ActiveInteractionContext]] -
返回 interaction context。
-
将内部
AsyncContext. Variable的值设置为 null。[[ ActiveInteractionContext]]
4. 交互内容绘制
4.1. InteractionContentfulPaint 接口
[Exposed =Window ]interface :InteractionContentfulPaint PerformanceEntry {readonly attribute LargestContentfulPaint ;largestContentfulPaint readonly attribute unsigned long long ;interactionId object (); };toJSON InteractionContentfulPaint includes PaintTimingMixin ;
每个 InteractionContentfulPaint
都具有:
-
一个关联的 context,一个 InteractionContext。
-
一个关联的 largest contentful paint,一个
LargestContentfulPaintentry。 -
一个关联的 paint timing info。
largestContentfulPaint
属性的 getter 必须返回 this 的
最大内容绘制。
interactionId
属性的 getter 必须返回 this 的
上下文的 id。
name
属性的 getter 必须返回空字符串。
entryType
属性的 getter 必须返回 。
startTime
属性的 getter 必须返回 this 的
上下文的 开始时间。
duration
属性的 getter 必须返回以下两者之间的差值:
默认绘制时间戳,针对 this 的绘制
计时信息;以及 this 的
上下文的 开始时间。
注: 虽然该条目会从其关联的 InteractionContext 动态查询静态
交互属性(如 interactionId 和
startTime),但它会在创建时捕获该
绘制的绘制计时信息以及候选 LargestContentfulPaint
条目的静态快照,以
确保这些指标反映该视觉更新的确切状态。
4.2. 交互内容绘制算法
Window
window、一个
InteractionContext interaction
context、一个 LargestContentfulPaint
lcpEntry,以及一个
paint timing info paintTimingInfo,要 create an interaction contentful paint entry:
-
令 entry 为 window 的 realm 中的一个新的
InteractionContentfulPaint对象。 -
将 entry 的 context 设置为 interaction context。
-
将 entry 的 largest contentful paint 设置为 lcpEntry。
-
将 entry 关联的 paint timing info 设置为 paintTimingInfo。
-
返回 entry。
-
如果 interaction context 的首次滚动时间戳 大于 0,并且 lcpEntry 的
renderTime大于 interaction context 的 首次滚动时间戳,则返回。 -
如果 interaction context 的首次输入时间戳大于 0,并且 lcpEntry 的
renderTime大于 interaction context 的 首次输入时间戳,则返回。 -
令 lcpEntry 为使用 lcpCandidate、paintTimingInfo 和 document 创建 LargestContentfulPaint 条目的结果。
-
令 global 为 document 的相关全局对象。
-
令 paint timing info 为 lcpEntry 的关联绘制计时信息。
-
令 icpEntry 为在给定 global、interaction context、lcpEntry 和 paint timing info 的情况下创建交互内容 绘制条目的结果。
-
入队 icpEntry。
-
将 icpEntry 添加到 global 的性能条目缓冲区。
-
如果 interaction context 的首次内容绘制为 null:
-
将 interaction context 的首次内容绘制 设置为 icpEntry。
-
-
将 interaction context 的最大内容绘制设置为 icpEntry。
-
将 interaction context 的当前最大 内容绘制候选 设置为 lcpCandidate。
注:InteractionContentfulPaint 条目在
被检测到时即会被发出到性能时间线,无论该交互最终是否产生软导航。这
允许开发者监控所有交互的渲染更新。
Document
document、一个 绘制定时信息 paintTimingInfo、一个由
待处理图像记录组成的有序
集合 paintedImages,以及一个由 元素组成的有序
集合
paintedTextNodes:
-
令 contextToCandidateSets 为一个新的映射。
-
对 paintedImages 的每个 record:
-
令 element 为 record 的元素。
-
令 interaction context 为针对 element获取绘制 归因交互上下文的结果。
-
如果 interaction context 不为 null:
-
-
对 paintedTextNodes 的每个 element:
-
令 interaction context 为针对 element获取绘制 归因交互上下文的结果。
-
如果 interaction context 不为 null:
-
-
对 contextToCandidateSets 中的每个 interaction context → candidateSets:
-
令 newCandidate 为给定 document、candidateSets[0]、candidateSets[1] 以及 interaction context 的 当前 最大内容绘制候选项计算新的 最大内容绘制候选项的结果。
-
如果 newCandidate 不为 null:
-
给定 newCandidate、 document、 interaction context 和 paintTimingInfo,处理 新的已归因内容绘制候选项。
-
给定 document 和 interaction context,评估软导航 发出。
-
-
4.3. 交互内容绘制归因
-
context,一个 InteractionContext,初始为 null。
-
modification id,一个 64 位无符号整数,初始为 0。
-
如果 other node state 为 null,或 node state 的 modification id大于 other node state 的 modification id,则返回 true, 否则返回 false。
-
令 document 为 node 的节点文档。
-
如果给定 document 时,target node 未暴露给绘制定时,则返回。
-
令 interaction context 为给定 document获取当前交互上下文的结果。
-
如果 interaction context 为 null,则返回。
-
如果 document 的最后修改上下文不等于 interaction context:
-
令 previous node state 为 document 的已标记节点 状态[target node] 默认值为 null。
-
如果 previous node state 不为 null,且 previous node state 的 modification id等于 document 的 当前修改代 id,则返回。
-
令 node state 为一个新的 InteractionPaintTimingNodeState。
-
将 node state 的context设置为 interaction context。
-
将 node state 的modification id设置为 document 的当前修改代 id。
-
将 document 的交互绘制定时为 脏设置为 true。
-
如果 document 的交互绘制定时为 脏为 false,则返回。
-
给定 document 和 null,更新节点及其后代的 交互上下文。
-
将 document 的交互绘制定时为 脏设置为 false。
-
令 document 为 node 的节点文档。
-
如果 node state 不为 null:
-
如果 inherited node state 不为 null,且 node 符合定时条件:
-
对 node 的每个子child node, 给定 child node 和 inherited node state,更新 节点及其后代的交互上下文。
注:为简单起见,每当需要重新处理传播状态时,此算法都会遍历整个
DOM。这可以优化为只处理 DOM 中可绘制的部分,例如
已知不可见或会被现有机制(如
content 或 CSS containment)跳过的子树,在此
过程中也可以被跳过,只要它们在下一次被绘制之前
得到更新即可。另请注意,这还可以通过
将这些步骤与另一次(绘制前)树遍历合并来进一步优化,只要相关状态在
绘制前得到更新即可。
注:[CONTAINER-TIMING] API 提供了一种 机制,用于按共同的 DOM 祖先对渲染效果进行分组,并将聚合后的绘制信息报告到性能时间线。在本规范的未来 版本中,我们计划扩展 Container Timing,以支持单个容器的多个客户端 (即全局 "containertiming" 属性和按交互定时),从而允许 基于 Container Timing 实现交互绘制定时。每个被记录的节点都将被 视为修改它的交互的容器,这样每个交互都会关联到一组容器。然后,本 规范将针对每个交互,跟踪在已标记容器中发生的最大内容绘制。此外,我们还可以暴露 Container Timing 跟踪的其他有用信息, 例如每个交互的容器聚合总绘制面积。
5. 软导航
5.1. PerformanceSoftNavigation 接口
[Exposed =Window ]interface :PerformanceSoftNavigation PerformanceEntry {readonly attribute NavigationType ;navigationType readonly attribute unsigned long long ;interactionId InteractionContentfulPaint ?(); };getLargestInteractionContentfulPaint PerformanceSoftNavigation includes PaintTimingMixin ;
每个 PerformanceSoftNavigation
都具有:
-
一个关联的 上下文,一个 InteractionContext。
-
一个关联的绘制计时信息。
navigationType
属性的 getter 必须返回 this 的
上下文的 导航类型。
interactionId
属性的 getter 必须返回 this 的
上下文的 id。
getLargestInteractionContentfulPaint()
方法必须返回 this 的
上下文的 最大内容绘制。
name
属性的 getter 必须返回 this 的
上下文的 第一个 URL
值。
entryType
属性的 getter 必须返回 。
startTime
属性的 getter 必须返回 this 的
上下文的 开始时间。
duration
属性的 getter 必须返回 this 的
presentationTime
与 this 的
上下文的
开始时间在发出时的差值。
注:在实践中,getLargestInteractionContentfulPaint()
预期会返回一个非 null
条目,因为已确认的软导航至少需要检测到一次交互内容绘制来
触发其发出。
不过,未来的迭代可以评估软导航是否可以在 URL 修改后、
第一次绘制之前立即被视为已提交。在这样的模型中,此方法可能会
在发出时返回 null。
此定时的主要设计考量是对其他时间线条目(例如
LayoutShift、PerformanceResourceTiming、LongAnimationFrameTiming 等)的归因,这些条目发生在
URL 修改与第一次绘制之间的间隔中。许多站点会在发起 fetch 请求时
立即提交新 URL,例如,即使当前页面仍处于
先前的导航状态。为确保一致的时间线切片,本规范会将所有
这类条目归因到先前的导航标识符,直到第一次绘制确认该转换。
5.2. 软导航算法
软导航是一种 满足以下条件的同文档导航:
-
当 InteractionContext 处于活动状态时,发生同文档 URL 变更。
-
发生一次内容绘制,并且该绘制被归因到同一个 InteractionContext。
-
如果 interaction context 的 已发出为 true,则返回。
-
如果 document 的活跃软导航候选 不是 interaction context,则返回。
-
如果 interaction context 的第一个 URL 值为 null,则返回。
-
如果 interaction context 的首次内容绘制为 null, 则返回。
-
令 window 为 document 的相关全局对象。
-
令 entry 为在给定 window 和 interaction context 的情况下创建 软导航条目的结果。
-
在给定 window 和 entry 的情况下,发出软导航条目。
-
将 interaction context 的 已发出设置为 true。
Window
window 和一个
InteractionContext interaction
context 的情况下创建
软导航条目:
Window
window 和一个
PerformanceSoftNavigation
entry 的情况下发出软
导航条目:
注: 这个 navigationId
对于此 PerformanceSoftNavigation
条目会在将其排入性能时间线时自动设置,
与其他
PerformanceEntry
类型的行为相匹配。
NavigationType
navigation type 的情况下处理
同文档提交:
-
如果 url 等于 document 的 url,则返回。
-
令 interaction context 为在给定 document 的情况下获取当前交互 上下文的结果。
-
如果 interaction context 为 null,则返回。
-
将 interaction context 的最后一个 URL 值设置为 url。
-
如果 interaction context 的首次 URL 更新时间戳为 null:
-
将 interaction context 的首次 URL 更新 时间戳设置为给定 document 的相关全局对象时的 当前高精度时间。
-
将 interaction context 的第一个 URL 值设置为 url。
-
将 interaction context 的导航类型设置为 navigation type。
-
-
将 document 的活跃软导航候选 设置为 interaction context。
-
在给定 document 和 interaction context 的情况下,评估软导航发出。
6. 规范集成
6.1. DOM 集成
6.1.1. Document
每个 document 都有一个 交互 id 到 交互上下文,即一个 映射, 初始为空。
每个 document 都有一个 活跃软导航 候选,即一个 InteractionContext 或 null,初始为 null。
每个 document 都有一个 当前修改 代 id,即一个 64 位无符号整数,初始化为 0。
注: 当相关 DOM 修改 以不同于上一次修改的 当前修改代 id 发生时,该 id 会变化 InteractionContext。 这允许将相关修改 归为一组,从而能够按新近程度比较 InteractionPaintTimingNodeState 对象 并优化需要跟踪哪些节点。
每个 document 都有一个 上一次修改 上下文,即一个 InteractionContext 或 null,初始为 null。
每个 document 都有一个 已标记节点状态,即一个从 映射 的 Node 到 InteractionPaintTimingNodeState, 初始为空。
每个 document 都有一个 已传播节点状态,即一个从 映射 的 Node 到 InteractionPaintTimingNodeState, 初始为空。
每个 document 都有一个 交互绘制 计时是否为脏,即一个布尔值, 初始为 false。
6.1.2. Node
-
元素的
或class style属性被修改。 -
资源属性(例如
img或video元素上的src)被修改。
运行以下步骤:
-
给定 node,将节点记录为 已为交互绘制定时而修改。
6.2. HTML 集成
6.2.1. History
documentsEntryChanged 为
true 且如果 documentIsNew 为 false)之前,给定该 处理一次同
document 提交,给定该 Document、
目标条目的 url,以及 "traverse"。
push"
或
"replace")。
6.2.2. 硬导航
当创建新的 Window
时(例如在“硬”导航期间),其
当前导航
id 会按 § 2.1 导航 ID 中的规定初始化。
PerformanceNavigationTiming
条目时,用户代理必须将其 navigationId 设置为该 Window
的
当前导航
id。
6.3. Event Timing 集成
本规范扩展了 [EVENT-TIMING] 对交互的定义,以包含与现代 Web 应用程序和单页应用程序相关的 其他事件类型。
以下事件类型被认为是交互的一部分(如 [EVENT-TIMING] 中所定义):
-
navigate -
popstate -
hashchange
当这些事件作为用户交互的结果被派发时,用户代理必须为它们分配
一个唯一的 interactionId,
该值通过为 document 的相关全局对象获取下一个 interactionId
而获得。如果某个事件由先前
已分配 interactionId
的交互触发,
用户代理应复用
该同一标识符。
注:这些事件只有在它们是由
用户操作发起的起始事件时(例如点击浏览器 UI 的后退按钮),才会作为主要
交互被报告。在大多数其他场景中——例如
click 处理器手动操作历史记录时——后续的 popstate 或 navigate 事件不会被
视为独立的用户交互。
虽然这些以编程方式触发的事件可能未设置 isTrusted
标志,但它们会通过 [ASYNC-CONTEXT] 被
正确归因回原始交互,因为历史和
导航 API 被视为发起任务的异步延续。
注:navigate、popstate 和 hashchange 事件会被用作内部信号,用于
跟踪软导航并分配 interactionId。本规范
不要求这些
事件类型作为 PerformanceEventTiming 条目暴露到
性能时间线,而是将
该决定留给 [EVENT-TIMING] 规范。
注:[EVENT-TIMING] 规范预期会被
更新,以显式定义
processingStart 和 processingEnd 钩子,并
确保 interactionId 分配发生得足够早,
以支持此集成。目前,interactionId 分配通常会
推迟到事件处理
结束时。
本规范使用
unsigned 作为 interactionId,
以确保安全的全局
计数器,而 [EVENT-TIMING]
目前将其定义为 unsigned 。预计
该不匹配会在两个规范的未来版本中解决。
Window
window 获取下一个
interactionId:
-
将 window 的interaction count 设置为 window 的 interaction count 加 1。
-
返回 window 的initial interactionId value 加上 (window 的interaction count 乘以 window 的interactionId increment)。
-
在将 timingEntry 设置为初始化并记录事件 定时处理开始结果的步骤之后,立即运行以下步骤:
-
给定 timingEntry,为事件分派设置当前 交互上下文。
-
-
在调用记录事件定时处理结束的步骤之前, 立即运行以下步骤:
6.4. Paint Timing 集成
本规范扩展了 [PAINT-TIMING] 规范,以便为 已由交互修改的元素重置绘制跟踪,并为已渲染的文档触发绘制归因。
标记绘制 时间混合了应在 UA 绘制文档之前和 之后发生的步骤。此处添加的步骤预期会在绘制前发生。[w3c/paint-timing Issue #126]
Document
document、一个 绘制定时信息 paintTimingInfo、
一个由 待处理图像记录组成的有序集合
paintedImages,以及一个由
元素组成的有序
集合 paintedTextNodes:
-
给定 document、 paintTimingInfo、paintedImages 和 paintedTextNodes,报告交互 内容绘制和软导航。
添加以下算法:
-
重置文本元素跟踪 node。
-
重置图像元素跟踪 node。
这是一个占位 算法。我们需要允许相关元素重新绘制,但这些 重新绘制不应影响 Element Timing 或 LCP。文本和图像具有不同的机制来 检测何时发生了相关绘制,并且二者都需要更新以支持重新绘制。
添加以下算法:
6.5. Largest Contentful Paint(LCP)集成
7. 安全与隐私考量
暴露到性能时间线的软导航本身没有安全和隐私影响。 但是,由于检测到软导航而重置各种绘制计时条目可能会产生影响,尤其是在已访问链接被分区之前。因此,在未分区 :visited 缓存的情况下暴露 此类绘制操作,需要仅在仔细分析相关绘制操作之后进行,以确保它们不会跨源暴露用户的历史记录。类似地,暴露详细的绘制计时信息(例如通过 Interaction Contentful Paint)
可能会被用于观察拼写或语法错误装饰(通过
或 )被应用时的绘制更新。在没有
缓解措施的情况下,这可能
允许攻击者以编程方式循环遍历文本字段中的单词,以检查它们是否
存在于用户的词典中。但是,浏览器通过将拼写和语法
检查限制为仅在每次用户交互(例如按键或点击)时发生一次来缓解此问题,以防止用户词典
泄露。由于计时和绘制
信息已经可以由开发者通过其他标准 API 观察到,因此暴露这些计时
条目不会引入任何新的信息泄露,超出浏览器拼写/语法高亮频率限制已经约束的范围。
8. 附录:重叠交互和竞态条件
Web 应用程序经常会快速连续地处理多个用户交互。本规范 通过以下模型处理这类重叠交互:
-
上下文独立性:每个交互都会独立管理自己的 InteractionContext。 多个上下文可以同时“进行中”,各自跟踪自己的 URL 修改和 内容绘制。
-
抢占:交互上下文在触发其首次同文档 URL 修改的那一刻成为 活动软导航候选项。 如果随后发生另一个交互 修改,它会抢占前一个交互,并成为新的候选项。
-
发出验证:只有在发出 条件(URL 变更 + 内容绘制)得到满足的那一刻,作为 活动软导航候选项 的交互上下文,才会发出
PerformanceSoftNavigation。 这确保软导航报告 与文档当前的视觉状态和导航状态保持一致。 -
持久归因:即使某个交互作为软导航 候选项被抢占, 只要它仍处于活动状态,它就会继续归因并报告自己的
InteractionContentfulPaint条目。这允许准确测量并发渲染更新,即使这些更新 本身不被视为“导航”。