用 K 线 API 构建可交互行情面板:历史数据加载与实时更新实践
系列文章 · Demo#2
在上一篇文章中,我实现了一个基于 Ticker API
的实时行情面板,解决的是"实时价格展示"的问题。但在实际使用中,一个更工程化的问题出现了:
实时快照只能告诉你"现在",却无法支撑时间序列分析。
因此,在 Demo #2 中,我对原有结构进行了一次完整升级 ------ 引入 K
线(蜡烛图)能力,并实现:
- 历史数据加载
- 当前周期实时补齐
- 预加载策略
- 可视范围控制
- 主从面板结构改造
一、结构升级:主从布局改造
原始 Demo #1 是全宽行情列表。
本次升级采用"主从布局":
- 左侧:简化行情列表
- 右侧:行情快照 + K 线图表
不引入新路由,不刷新页面,仅通过状态控制 DOM 展开。
结构示意如下:

工程目标:
- 不破坏原有 Ticker 刷新逻辑
- 不增加页面跳转复杂度
- 保持组件解耦
二、接口职责拆分:History vs Latest
核心接口:
/kline------ 返回已完成周期的历史数据/kline/latest------ 返回当前正在形成的周期数据
工程逻辑必须分层处理:
pseudo
// 1. 先加载历史数据
historyData = await fetchKLine(symbol, interval, 75)
// 2. 获取当前周期
latestKline = await fetchLatestKLine(symbol, interval)
// 3. 合并逻辑
if latestKline exists:
if same timestamp:
replace
else:
push
设计原则:
- 历史数据只负责结构化展示\
- latest 只负责补齐当前周期\
- 两层逻辑完全解耦
否则会出现时间错位或重复渲染问题。
三、时间序列处理的关键细节
接口数据存在两个常见坑:
1️⃣ 时间戳单位问题
接口返回毫秒,图表库使用秒。
pseudo
time: Math.floor(item.time / 1000)
2️⃣ 返回顺序问题
接口默认倒序,图表需要升序。
pseudo
klineData.sort((a, b) => a.time - b.time)
完整转换逻辑:
pseudo
const rawKlines = result.data.klines
const klineData = rawKlines.map(item => ({
time: Math.floor(item.time / 1000),
open: parseFloat(item.open),
high: parseFloat(item.high),
low: parseFloat(item.low),
close: parseFloat(item.close)
}))
klineData.sort((a, b) => a.time - b.time)
四、预加载策略:Buffer 设计
如果用户滑到最左侧才加载历史数据,会出现明显卡顿。
我采用"可视区 + Buffer"策略:
|------------------ 75 ------------------|
|------ 50 visible ------|-- 25 buffer --|
加载策略:
- 首次加载 75 根
- 可见区约 50 根
- 预留 25 根 buffer
- 当 buffer 消耗 50% 时触发加载
核心判断逻辑:
pseudo
if leftBufferCount < batchLoad * triggerRatio:
preloadHistoricalData()
五、Resize 与可视范围控制
浏览器宽度变化会改变可见 K 线数量。
使用 ResizeObserver:
pseudo
const resizeObserver = new ResizeObserver(() => {
const currentRange = chart.timeScale().getVisibleLogicalRange()
chart.applyOptions({
width: container.clientWidth,
height: container.clientHeight
})
chart.timeScale().setVisibleLogicalRange(currentRange)
})
六、分层错误处理
pseudo
loadHistory() → 失败显示错误
preload() → 静默失败
loadLatest() → 不影响主图
原则:稳定性优先于完整性。
七、工程分层总结
1️⃣ 数据层 ------ History / Latest 分层
2️⃣ 视图层 ------ 主从结构 + 响应式图表
3️⃣ 交互层 ------ 预加载 + 滑动控制
最终效果

结语
从 Demo #1 的实时行情展示,到 Demo #2 的时间序列管理,系统结构更加完整。
源码可在 GitHub 搜索 tickdb-demo-ticker-panel 查看对应 Demo#2 实现。