实时界面模式
应用乐观更新以提供即时反馈,离线时使用本地队列,并比较传入数据,仅更新界面中发生变化的项目。
实时界面模式 是 CoddyKit 上的免费 Frontend Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Frontend Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Frontend Academy 课程共包含 4 节课。
实时意味着真实的交互体验
实时体验不仅意味着速度快,还意味着响应及时、行为可预测,并且能够包容延迟。三种核心模式是:乐观更新、本地排队和智能差异比较。
乐观更新
在服务器确认之前,用户执行操作后立即更新界面。如果服务器拒绝该操作,则回滚更新。这会让应用感觉即时响应。
async function likePost(id) {
// 1. Optimistically update UI:
setLikes(l => ({ ...l, [id]: (l[id] || 0) + 1 }));
setLiked(prev => ({ ...prev, [id]: true }));
try {
await fetch(`/api/posts/${id}/like`, { method: 'POST' });
} catch (err) {
// 2. Rollback on failure:
setLikes(l => ({ ...l, [id]: (l[id] || 1) - 1 }));
setLiked(prev => ({ ...prev, [id]: false }));
toast.error('Could not like — please retry');
}
}使用临时 ID 的乐观更新
对于新创建的项目,请先在本地为其分配临时 ID。响应到达后,再将其替换为服务器生成的真实 ID。
async function addComment(text) {
const tempId = `tmp-${Date.now()}`;
setComments(c => [...c, { id: tempId, text, pending: true }]);
try {
const saved = await fetch('/api/comments', {
method: 'POST',
body: JSON.stringify({ text })
}).then(r => r.json());
setComments(c => c.map(m => m.id === tempId ? saved : m));
} catch (err) {
setComments(c => c.map(m => m.id === tempId ? { ...m, error: true } : m));
}
}离线时进行本地排队
网络中断时,请将操作放入本地队列,网络恢复后再重放。这样用户可以继续工作。
const queue = JSON.parse(localStorage.getItem('queue') || '[]');
function enqueue(action) {
queue.push(action);
localStorage.setItem('queue', JSON.stringify(queue));
trySend();
}
async function trySend() {
while (queue.length && navigator.onLine) {
const action = queue[0];
try {
await fetch(action.url, action);
queue.shift();
localStorage.setItem('queue', JSON.stringify(queue));
} catch {
break; // stop until online
}
}
}
window.addEventListener('online', trySend);比较传入的实时数据
如果服务器推送整个列表,请将其与当前状态进行差异比较,只更新发生变化的部分,从而避免不必要的重新渲染和动画闪烁。
function applyServerSnapshot(newList, currentList) {
const current = new Map(currentList.map(i => [i.id, i]));
const result = newList.map(item => {
const prev = current.get(item.id);
if (!prev) return { ...item, _state: 'new' };
if (prev.updatedAt !== item.updatedAt) return { ...item, _state: 'updated' };
return prev;
});
return result;
}基于补丁的更新
这比完整快照更好:服务器只发送发生变化的字段。请逐步应用这些变化,这样可以减少带宽使用并加快渲染速度。
// Server sends: { type: 'patch', id: 42, fields: { likes: 11 } }
ws.on('message', (msg) => {
if (msg.type === 'patch') {
setPosts(posts => posts.map(p =>
p.id === msg.id ? { ...p, ...msg.fields } : p
));
}
});限制高频更新
某些数据流每秒会发送大量更新(鼠标位置、股票行情)。请将界面更新限制在约 60Hz,以避免浏览器卡顿。
import { throttle } from 'lodash-es';
const applyUpdate = throttle((data) => {
setData(data);
}, 16); // ~60fps
ws.on('tick', applyUpdate);在线状态指示器
实时显示其他在线或正在输入的用户。服务器发布在线状态事件,客户端使用头像渲染列表。
ws.on('presence', ({ users }) => {
setOnlineUsers(users);
});
ws.on('typing', ({ user, isTyping }) => {
setTypingUsers(t => isTyping
? [...t.filter(u => u.id !== user.id), user]
: t.filter(u => u.id !== user.id));
});连接状态横幅
离线或正在重新连接时,显示一个不显眼的横幅。完全重新连接后将其隐藏。当用户能够看到当前发生的情况时,他们对延迟的容忍度会高得多。
{!isConnected && (
<div className="connection-banner">
Reconnecting... Your changes will sync when you're back online.
</div>
)}冲突解决
实时应用必须处理并发编辑之间的冲突。策略包括:最后写入获胜(简单但可能丢失数据)、版本向量、OT(操作转换)和 CRDT(Yjs、Automerge)。
用于协作的 CRDT
CRDT(无冲突复制数据类型)支持在没有中央服务器的情况下进行实时协作编辑。相关库包括:Yjs、Automerge。Figma、Linear 和 Notion 风格的应用都在使用它们。
性能:虚拟化列表
实时信息流可能会变得很长。请使用虚拟化列表(react-virtuoso、@tanstack/react-virtual),只渲染可见项目——无论总数量多少,内存和 CPU 使用量都能保持稳定。
快速检查
实时界面中的“乐观更新”是什么?
回顾:实时界面模式
乐观更新让应用感觉即时响应,失败时则回滚。为新创建的项目使用临时 ID。使用本地排队确保离线时也能持久保存操作。对服务器更新进行差异比较或应用补丁,以避免重新渲染。限制高频数据流的更新频率。显示在线、正在输入等在线状态以及连接横幅。使用 CRDT(Yjs、Automerge)进行协作编辑。对较长的实时列表进行虚拟化。
常见问题解答
「实时界面模式」课时是免费的吗?
是的 — 「实时界面模式」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Frontend Academy 课程的其余内容,请升级到 CoddyKit PRO。 Frontend Academy 课程共包含 4 节课。
「实时界面模式」这节课中我会学到什么?
应用乐观更新以提供即时反馈,离线时使用本地队列,并比较传入数据,仅更新界面中发生变化的项目。 你通过在浏览器中直接运行的动手代码来练习 Frontend Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Frontend Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Frontend Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「实时界面模式」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Frontend Academy 课中编写并运行代码吗?
能。每节 Frontend Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。