开发预览 更新于 2026-05-10

TimingBar 请求瀑布

横向请求阶段瀑布图,每段一个 phase。

基础用法

数据通过 props 传入,纯 SVG 渲染,无第三方图表库依赖。 配色取自 --viz-1..8 token,色盲友好。

背景 视口
DNS: 12msConnect: 26msTLS: 54msTTFB: 153msDownload: 67msDNS 12msConnect 26msTTFB 153msDownload 67ms
src/App.vue
<script setup lang="ts">
import { CfTimingBar } from '@chufix-design/vue';
const phases = [
  { label: 'DNS', start: 0, end: 12, colorIndex: 6 },
  { label: 'Connect', start: 12, end: 38, colorIndex: 0 },
  { label: 'TLS', start: 38, end: 92, colorIndex: 2 },
  { label: 'TTFB', start: 92, end: 245, colorIndex: 1 },
  { label: 'Download', start: 245, end: 312, colorIndex: 3 },
];
</script>
<template>
  <CfTimingBar :phases="phases" />
</template>
<script setup>
import { CfTimingBar } from '@chufix-design/vue';
const phases = [
  { label: 'DNS', start: 0, end: 12, colorIndex: 6 },
  { label: 'Connect', start: 12, end: 38, colorIndex: 0 },
  { label: 'TLS', start: 38, end: 92, colorIndex: 2 },
  { label: 'TTFB', start: 92, end: 245, colorIndex: 1 },
  { label: 'Download', start: 245, end: 312, colorIndex: 3 },
];
</script>
<template>
  <CfTimingBar :phases="phases" />
</template>
import { CfTimingBar } from '@chufix-design/react';

export default function Demo() {
  const phases = [
    { label: 'DNS', start: 0, end: 12, colorIndex: 6 },
    { label: 'Connect', start: 12, end: 38, colorIndex: 0 },
    { label: 'TLS', start: 38, end: 92, colorIndex: 2 },
    { label: 'TTFB', start: 92, end: 245, colorIndex: 1 },
    { label: 'Download', start: 245, end: 312, colorIndex: 3 },
  ];
  return (
    <>
      <CfTimingBar phases={phases} />
    </>
  );
}
import { CfTimingBar } from '@chufix-design/react';

export default function Demo() {
  const phases = [
    { label: 'DNS', start: 0, end: 12, colorIndex: 6 },
    { label: 'Connect', start: 12, end: 38, colorIndex: 0 },
    { label: 'TLS', start: 38, end: 92, colorIndex: 2 },
    { label: 'TTFB', start: 92, end: 245, colorIndex: 1 },
    { label: 'Download', start: 245, end: 312, colorIndex: 3 },
  ];
  return (
    <>
      <CfTimingBar phases={phases} />
    </>
  );
}

真实瀑布场景

3 个并发 HTTP 请求的 timing 拼接:DNS / Connect / TLS / Wait / Receive 各色。

背景 视口
GET /v1/me · 264ms
DNS: 8msConnect: 24msTLS: 48msWait: 140msReceive: 44msDNS 8msConnect 24msWait 140msReceive 44ms
GET /v1/orders (cached) · 220ms
Wait: 184msReceive: 36msWait 184msReceive 36ms
POST /v1/charges · 480ms
Wait: 412msReceive: 68msWait 412msReceive 68ms
src/App.vue
<script setup lang="ts">
import { CfTimingBar } from '@chufix-design/vue';
// 真实场景:3 个并发 HTTP 请求
const r1 = [
  { label: 'DNS', start: 0, end: 8, colorIndex: 6 },
  { label: 'Connect', start: 8, end: 32, colorIndex: 0 },
  { label: 'TLS', start: 32, end: 80, colorIndex: 2 },
  { label: 'Wait', start: 80, end: 220, colorIndex: 1 },
  { label: 'Receive', start: 220, end: 264, colorIndex: 3 },
];
const r2 = [
  { label: 'Wait', start: 0, end: 184, colorIndex: 1 },
  { label: 'Receive', start: 184, end: 220, colorIndex: 3 },
];
const r3 = [
  { label: 'Wait', start: 0, end: 412, colorIndex: 5 },
  { label: 'Receive', start: 412, end: 480, colorIndex: 3 },
];
</script>
<template>
  <div style="display: flex; flex-direction: column; gap: 12px;">
    <div style="font-size: 11px; color: var(--fg-3); font-family: var(--font-mono);">GET /v1/me · 264ms</div>
    <CfTimingBar :phases="r1" />
    <div style="font-size: 11px; color: var(--fg-3); font-family: var(--font-mono);">GET /v1/orders (cached) · 220ms</div>
    <CfTimingBar :phases="r2" />
    <div style="font-size: 11px; color: var(--fg-3); font-family: var(--font-mono);">POST /v1/charges · 480ms</div>
    <CfTimingBar :phases="r3" />
  </div>
</template>
<script setup>
import { CfTimingBar } from '@chufix-design/vue';
// 真实场景:3 个并发 HTTP 请求
const r1 = [
  { label: 'DNS', start: 0, end: 8, colorIndex: 6 },
  { label: 'Connect', start: 8, end: 32, colorIndex: 0 },
  { label: 'TLS', start: 32, end: 80, colorIndex: 2 },
  { label: 'Wait', start: 80, end: 220, colorIndex: 1 },
  { label: 'Receive', start: 220, end: 264, colorIndex: 3 },
];
const r2 = [
  { label: 'Wait', start: 0, end: 184, colorIndex: 1 },
  { label: 'Receive', start: 184, end: 220, colorIndex: 3 },
];
const r3 = [
  { label: 'Wait', start: 0, end: 412, colorIndex: 5 },
  { label: 'Receive', start: 412, end: 480, colorIndex: 3 },
];
</script>
<template>
  <div style="display: flex; flex-direction: column; gap: 12px;">
    <div style="font-size: 11px; color: var(--fg-3); font-family: var(--font-mono);">GET /v1/me · 264ms</div>
    <CfTimingBar :phases="r1" />
    <div style="font-size: 11px; color: var(--fg-3); font-family: var(--font-mono);">GET /v1/orders (cached) · 220ms</div>
    <CfTimingBar :phases="r2" />
    <div style="font-size: 11px; color: var(--fg-3); font-family: var(--font-mono);">POST /v1/charges · 480ms</div>
    <CfTimingBar :phases="r3" />
  </div>
</template>
import { CfTimingBar } from '@chufix-design/react';

export default function Demo() {
  // 真实场景:3 个并发 HTTP 请求
  const r1 = [
    { label: 'DNS', start: 0, end: 8, colorIndex: 6 },
    { label: 'Connect', start: 8, end: 32, colorIndex: 0 },
    { label: 'TLS', start: 32, end: 80, colorIndex: 2 },
    { label: 'Wait', start: 80, end: 220, colorIndex: 1 },
    { label: 'Receive', start: 220, end: 264, colorIndex: 3 },
  ];
  const r2 = [
    { label: 'Wait', start: 0, end: 184, colorIndex: 1 },
    { label: 'Receive', start: 184, end: 220, colorIndex: 3 },
  ];
  const r3 = [
    { label: 'Wait', start: 0, end: 412, colorIndex: 5 },
    { label: 'Receive', start: 412, end: 480, colorIndex: 3 },
  ];
  return (
    <>
      <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
          <div style={{ fontSize: 11, color: "var(--fg-3)", fontFamily: "var(--font-mono)" }}>GET /v1/me · 264ms</div>
          <CfTimingBar phases={r1} />
          <div style={{ fontSize: 11, color: "var(--fg-3)", fontFamily: "var(--font-mono)" }}>GET /v1/orders (cached) · 220ms</div>
          <CfTimingBar phases={r2} />
          <div style={{ fontSize: 11, color: "var(--fg-3)", fontFamily: "var(--font-mono)" }}>POST /v1/charges · 480ms</div>
          <CfTimingBar phases={r3} />
        </div>
    </>
  );
}
import { CfTimingBar } from '@chufix-design/react';

export default function Demo() {
  // 真实场景:3 个并发 HTTP 请求
  const r1 = [
    { label: 'DNS', start: 0, end: 8, colorIndex: 6 },
    { label: 'Connect', start: 8, end: 32, colorIndex: 0 },
    { label: 'TLS', start: 32, end: 80, colorIndex: 2 },
    { label: 'Wait', start: 80, end: 220, colorIndex: 1 },
    { label: 'Receive', start: 220, end: 264, colorIndex: 3 },
  ];
  const r2 = [
    { label: 'Wait', start: 0, end: 184, colorIndex: 1 },
    { label: 'Receive', start: 184, end: 220, colorIndex: 3 },
  ];
  const r3 = [
    { label: 'Wait', start: 0, end: 412, colorIndex: 5 },
    { label: 'Receive', start: 412, end: 480, colorIndex: 3 },
  ];
  return (
    <>
      <div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
          <div style={{ fontSize: 11, color: "var(--fg-3)", fontFamily: "var(--font-mono)" }}>GET /v1/me · 264ms</div>
          <CfTimingBar phases={r1} />
          <div style={{ fontSize: 11, color: "var(--fg-3)", fontFamily: "var(--font-mono)" }}>GET /v1/orders (cached) · 220ms</div>
          <CfTimingBar phases={r2} />
          <div style={{ fontSize: 11, color: "var(--fg-3)", fontFamily: "var(--font-mono)" }}>POST /v1/charges · 480ms</div>
          <CfTimingBar phases={r3} />
        </div>
    </>
  );
}

API

属性类型默认值说明
phasesTimingPhase[]{ label, start, end, colorIndex? }[](ms)
showAxisbooleantrue底部段标签
labelMode'auto' | 'all' | 'none''auto'段标签显示策略,默认自动避让重叠
totalLabelstring顶部右侧的总耗时标签(如 "1.4 s"
widthnumber480SVG 宽度
heightnumber28SVG 高度
ariaLabelstring透传给根 <svg>aria-label

Events

Vue 事件React 回调载荷类型说明
item-enteronItemEnterTimingBarInteractionPayload鼠标进入某 phase 时触发
item-leaveonItemLeaveTimingBarInteractionPayload鼠标离开某 phase 时触发

类型

interface TimingBarInteractionPayload {
  phase: TimingPhase;
  dataIndex: number;
  /** end - start,单位 ms */
  duration: number;
  nativeEvent?: PointerEvent;
}

反馈与讨论

TimingBar 请求瀑布 的讨论

0
0 / 600
正在加载评论...