普通视图

发现新文章,点击刷新页面。
今天 — 2026年5月5日首页

2026年五一档档期票房破7亿元

2026年5月5日 13:26
据猫眼专业版数据,截至5月5日13时7分,2026年五一档(5月1日—5月5日)总票房破7亿元,《消失的人》《寒战1994》《穿普拉达的女王2》分列档期票房榜前三位。

高通前高管将加入英特尔,领导客户端计算与物理AI事业部

2026年5月5日 13:00
5月5日,英特尔公司宣布两项重要领导层任命。Alex Katouzian将于5月加入英特尔,担任执行副总裁兼客户端计算与物理AI事业部总经理。Katouzian此前任职于高通技术公司,担任执行副总裁兼手机、计算和XR事业群总经理。 英特尔同时宣布,正式任命此前担任代理首席技术官的Pushkar Ranade出任首席技术官。作为首席技术官,他将推进公司技术战略,主导专项技术项目,并推动量子计算、神经拟态计算、光子学及新型材料等关键新兴领域的发展。 Katouzian与Ranade将直接向首席执行官陈立武汇报。(界面新闻)

中国移动将推出AI-eSIM产品

2026年5月5日 12:42
5月5日,中国移动发布消息称,5月7日-9日,2026移动云大会将在苏州金鸡湖国际会议中心举办,届时将推出AI-eSIM产品。据介绍,该产品可以实时调度云端模型,让设备能自主思考、即时响应,可应用于AI玩具、智慧穿戴等终端。

广汽丰田4月销量54116台

2026年5月5日 12:21
5月5日,广汽丰田公布,2026年4月销量54116台,上年同期销量60038台。其中,铂智3X当月销量10027台,再创历史新高;铂智7上市首月交付4637台。

苹果考虑让英特尔、三星代工设备处理器

2026年5月5日 12:09
苹果公司正与英特尔、三星电子洽谈,计划将设备主处理器交由这两家企业生产,作为台积电之外的备选供应商。目前苹果与英特尔、三星的谈判仍处于初步阶段,尚未下达任何订单。苹果对采用非台积电技术仍存顾虑。受供应链中断影响(包括近期 AI 数据中心建设热潮、Mac 需求超预期导致的芯片短缺),苹果正考虑增加供应商,以缓解产能瓶颈、避免增长受限。 苹果、英特尔、三星及台积电的发言人均拒绝置评。 (环球市场播报)

白宫拟在AI模型发布前实施审查

2026年5月5日 11:50
特朗普政府正考虑发布一项行政令,成立人工智能工作组,旨在加强对这一新兴技术的监管。其中一项提案要求对新AI模型实施政府审查流程。该报称,白宫官员在上周的会议中,已向Anthropic、谷歌母公司Alphabet以及OpenAI的高管通报了部分拟议计划。(第一财经)

今天全国铁路预计发送旅客2300万人次

2026年5月5日 11:27
假期接近尾声,铁路迎来返程客流高峰,客流持续保持高位运行。今天,全国铁路预计发送旅客2300万人次,计划加开旅客列车2225列。昨天,全国铁路发送旅客2038.3万人次,运输安全平稳有序。(央视新闻)

去哪儿旅行:五一“宝藏小城串游”预订量增121%

2026年5月5日 11:14
5月5日,去哪儿旅行数据显示,2026年“五一”假期整体旅游出行热度稳中有升。平台上人均打卡城市达2.1个,入住2个及以上城市酒店的“宝藏小城串游”预订量同比增长121%,3天以上租车订单占比超六成,异地租还车订单量同比增80%。

4月份中国大宗商品价格指数为132.1点 同比上涨20.2%

2026年5月5日 10:34
中国物流与采购联合会5月5日公布4月份中国大宗商品价格指数。4月份中国大宗商品价格指数为132.1点,环比上涨1.7%,同比上涨20.2%。在中国物流与采购联合会重点监测的50种大宗商品中,4月价格环比上涨的大宗商品有38种。其中,对二甲苯、甲醇和聚丙烯涨幅居前,较上月环比分别上涨22.4%、14.5%和11.8%。(央视新闻)

百威亚太:一季度收入14.93亿美元 同比下降0.7%

2026年5月5日 10:11
百威亚太5日早间披露一季度业绩,2026年第一季度总销量增长0.1%,为19737十万公升啤酒,这得益于集团在印度的强劲表现及中国行业状况的改善,但被韩国的发货安排时间差所抵销。由于中国额外投资,2026年第一季度收入14.93亿美元,同比下降0.7%,而每百升收入减少0.8%。(财联社)

剂泰科技寻求通过香港IPO募资21.1亿港元

2026年5月5日 09:48
根据提交给香港交易所的文件,剂泰科技(北京)股份有限公司香港上市拟发行2.01亿股股票,每股发行价10.50港币。据估算,该公司势将融资21.1亿港元(2.69亿美元)。该公司将于5月13日挂牌上市,Jefferies、德意志银行和中信证券是联席保荐人。(新浪财经)

马斯克就推特持股披露诉讼与美证监会达成和解

2026年5月5日 09:27
当地时间5月4日,埃隆·马斯克已就美国证券交易委员会提起的民事诉讼达成和解。该诉讼指控其在2022年未及时披露其初始购买推特(现称X)持股的行为。根据当天华盛顿特区联邦法院披露的和解协议,以马斯克名义设立的信托将支付150万美元民事罚款。马斯克未承认存在不当行为,且无需退还其因延迟披露而声称节约的1.5亿美元资金。(界面新闻)

抖音集团副总裁:网传所谓红果短剧收费的消息不实

2026年5月5日 09:04
5月4日深夜,抖音集团副总裁李亮在社交平台发文表示,网传所谓红果短剧收费的消息不实,实际情况是:为持续丰富平台视频内容生态,满足大家多样化的观看需求,红果短剧陆续引入了一些影视内容。依据相关影视版权方合规要求与行业惯例,该部分少数影视内容需开通VIP权限观看。而免广告会员服务,只是满足用户差异化体验的自愿选项,不会强制收费,也不会改变用户免费追剧的核心模式。不管是免广告的VIP服务,还是极少量需VIP才能观看的影视内容,都是2024年2月红果早期就有的功能,并不是近期的新动作。

TCP/IP 与前端性能:从数据包到首次渲染的底层逻辑

2026年5月4日 21:23

TCP/IP 与前端性能:从数据包到首次渲染的底层逻辑

这是“从 URL 到页面展示”系列第三篇。前面两篇我们聊完了浏览器导航DNS 与传输层细节,今天我们钻进 TCP/IP 协议栈的核心,看看一个数据包究竟怎么跑完全程,以及它为什么直接影响前端最关心的性能指标 FP(首次渲染时间)


一、前端性能的起点:FP 与 TTFB

面试官问“怎么优化页面加载速度”,你可以先说两个关键时间点:

  • TTFB(Time To First Byte):从发起请求到收到服务器第一个字节的耗时 = DNS 解析 + TCP/TLS 连接 + 服务器处理 + 响应传输的第一个字节到达。
  • FP(First Paint):从页面加载到浏览器首次绘制出像素的耗时 = TTFB + HTML 解析 + CSSOM 构建 + 渲染树构建 + 布局 + 首次绘制。

从这个公式可以看出:TTFB 里有一大块时间花在网络传输上,而网络传输的根基就是 TCP/IP。前端做性能优化,不能只盯着 JS 和 CSS,还得懂底层。


二、数据包的旅程:互联网的“快递系统”

互联网本质是一套理念和协议组成的体系架构,数据不是一整块丢进网线的,而是拆成一个一个数据包传输。

为什么拆包?

  • 单个文件可能几十 MB,一次性发送会长时间占用整条链路,其它请求就得排队。
  • 拆成小包后,可以利用带宽并发传输,提升传输效率和容错率。某个包丢了,只需要重发这一个,不用重发全部。

这些数据包最终会变成二进制数据帧,在物理介质上流动。


三、IP 层:只负责“送到”,不负责“送到位”

IP(Internet Protocol)是网络层的协议,职责非常单纯:根据 IP 地址,把数据包从源主机送到目标主机

它做的是“尽力而为”的服务:

  • 可能丢包
  • 可能出错
  • 可能不按顺序到达
  • 不提供任何纠正机制

所以 IP 本身是一个“不可靠”的协议。前端请求的 HTML 文件结构严密,一个字节错位都可能导致渲染异常,怎么办?

答案就在传输层。


四、UDP vs TCP:两种“快递模式”

传输层运行在 IP 之上,负责将数据包交付到目标主机上的具体应用(通过端口号)。主要有两位选手:

UDP(User Datagram Protocol):只管快

  • 不建立连接,直接发包。
  • 不保证顺序,不重传丢失的包。
  • 头部开销小,速度快。

适用场景:对实时性要求极高、能容忍少量数据丢失的音视频直播、视频通话、在线游戏。

TCP(Transmission Control Protocol):保证到位

对于 HTML、CSS、JS、图片这类 Web 资源,哪怕一个包出错都可能导致页面渲染异常。TCP 专门解决两个核心问题:

问题 TCP 的解法
数据包在传输过程中丢失 超时重传机制 — 每发一个包,启动一个计时器,过期未收到确认就重发
数据包到达接收端顺序错乱 序号机制 — 每个包都带有序号,接收端按序号重新组装

因为要保证可靠性,TCP 比 UDP 慢 —— 但这恰恰是 Web 页面需要的可靠传输


五、三次握手:建立可靠连接

在真正发送 HTTP 请求之前,TCP 需要通过三次握手建立连接。核心目的:同步初始序号,验证双方收发能力

简化过程:

  1. 客户端 → 服务器SYN,带上初始序号 J
    “我想和你建立连接,我发送的包从 J 开始编号,你听得到吗?”

  2. 服务器 → 客户端SYN + ACK,确认号 J+1,同时带上自己的初始序号 K
    “听到了,你下一个从 J+1 开始发。我也想和你建立连接,我的包从 K 开始编号,你听得到吗?”

  3. 客户端 → 服务器ACK,确认号 K+1
    “听到了,你下一个从 K+1 开始发。咱们可以正式开始传数据了。”

高频追问:为什么是三次,不是两次或四次?

  • 两次不够:服务器无法确认客户端能收到自己的消息(无法确认客户端有接收能力)。
  • 四次没必要:第二次握手时,服务器把 “响应客户端的 SYN”“发出自己的 SYN” 合并成一条消息,效率最大化。
    原则是:每一方的发送和接收能力都需要两次验证,但因为服务器把两个动作合并了,总共只需三次。

过程图

image.png

六、四次挥手:优雅地断开连接

数据传输完毕(比如 HTML 下载完成、图片加载结束),需要断开 TCP 连接释放资源。这个过程需要四次挥手

  1. A → BFIN,带上序号 M
    “我没有数据要发了,想断开连接。”

  2. B → AACK,确认号 M+1
    “知道你没数据了,但我可能还有数据没发完,你再等等。”

  3. B → AFIN,带上序号 N
    “我的数据也发完了,可以断开了。”

  4. A → BACK,确认号 N+1
    “好的,我知道你也没数据了。再见。”

为什么比握手多一次?因为 TCP 是全双工的,双方都可以独立发送和接收数据。一端说“我发完了”,另一端可能还有数据要传,所以 FIN 和 ACK 不能合并,必须分开发送,正好四次。

过程图

image.png


七、回到前端:这些对性能优化意味着什么?

理解了 TCP,就能看懂很多性能优化的底层逻辑:

优化手段 背后的 TCP 原理
减少 HTTP 请求数(雪碧图、合并文件) 每个 TCP 连接都有三次握手开销,请求数越少,握手成本越低
使用 HTTP/2 多路复用 单个 TCP 连接上并发传输多个请求和响应,避免重复握手
启用 TCP Fast Open 在握手阶段就开始传数据,将握手和数据传输部分重叠,降低 TTFB
使用 CDN 缩短物理距离 → 减少 RTT(往返时延)→ 丢包概率降低 → 重传少 → 更快
资源预连接(preconnect) 提前完成 DNS + TCP + TLS 握手,请求时直接使用已建立的连接

八、总结:一条链路串起知识体系

至此,我们串联起了整个前端性能链条的网络部分:

DNS 解析(IP 找到主机)
  → TCP 三次握手(建立可靠连接)
  → TLS 握手(加密安全)
  → HTTP 请求/响应(应用层数据)
  → TCP 四次挥手(断开连接)

每一个环节的耗时,都叠加进了 TTFB,进而影响 FP。下次面试问到性能优化,你完全可以从这个底层视角切入,展示你对网络协议栈的真懂,而不是只背“减少请求数”的表面答案。


代码写成一锅粥?3个设计模式让你的项目“起死回生”

作者 kyriewen
2026年5月4日 21:01

你的组件里是不是全是if-else?改一个地方,崩三个地方?新来的同事改完你的代码,你看着他,他看你,两人都沉默了。今天我们不背理论,直接用3个前端最常用的设计模式——单例、观察者、策略,把业务从“屎山”变成“积木”。学完你就能拍着胸脯说:“我的代码,谁都敢动。”

前言

设计模式不是“面试八股文”,而是前辈们踩过的坑总结成的“套路”。就像做饭有菜谱,写代码也有标准解法。今天我们把场景摆出来:弹窗多次打开、购物车更新通知到处写、表单校验if-else十几层……然后一个个用设计模式把它们治好。

一、单例模式:全局只有一个的“独生子”

场景:你写了个全局弹窗(Modal),用户点按钮就打开。结果用户连续点三次,页面上冒出三个弹窗叠在一起,像俄罗斯方块。

问题代码

function showModal() {
  const div = document.createElement('div');
  div.className = 'modal';
  div.innerHTML = '我是弹窗';
  document.body.appendChild(div);
}
// 点三次,三个弹窗

单例模式解决

确保无论调用多少次,只创建同一个实例。

class GlobalModal {
  constructor() {
    if (!GlobalModal.instance) {
      this.element = null;
      GlobalModal.instance = this;
    }
    return GlobalModal.instance;
  }
  show() {
    if (!this.element) {
      this.element = document.createElement('div');
      this.element.className = 'modal';
      this.element.innerHTML = '我是弹窗';
      document.body.appendChild(this.element);
    }
    this.element.style.display = 'block';
  }
  hide() {
    if (this.element) this.element.style.display = 'none';
  }
}
const modal1 = new GlobalModal();
const modal2 = new GlobalModal();
console.log(modal1 === modal2); // true

真实项目更简单的写法:直接导出实例对象。

// modal.js
export const globalModal = {
  element: null,
  show() { /* ... */ },
  hide() { /* ... */ }
};

应用:全局Store(Pinia/Vuex就是单例)、全局轮询管理器、WebSocket连接。

二、观察者模式:让不相干的组件“悄悄对话”

场景:用户点击“添加购物车”,需要同时做三件事:更新购物车角标、弹出“添加成功”提示、发送埋点数据。如果直接在购物车里调用其他模块的方法,代码会变成:

function addToCart(item) {
  // 添加逻辑...
  header.updateBadge(count);
  toast.show('添加成功');
  analytics.track('add_to_cart', item);
}

每加一个功能,addToCart就要改一次,耦合得像麻花。

观察者模式解决(事件总线)

// eventBus.js
class EventBus {
  constructor() {
    this.events = {};
  }
  on(event, callback) {
    if (!this.events[event]) this.events[event] = [];
    this.events[event].push(callback);
  }
  emit(event, data) {
    if (this.events[event]) {
      this.events[event].forEach(cb => cb(data));
    }
  }
  off(event, callback) {
    if (this.events[event]) {
      this.events[event] = this.events[event].filter(cb => cb !== callback);
    }
  }
}
export const bus = new EventBus();
// 购物车模块
import { bus } from './eventBus';
function addToCart(item) {
  // 添加逻辑...
  bus.emit('cartUpdated', { count: newCount, item });
}
// 头部模块
import { bus } from './eventBus';
bus.on('cartUpdated', (data) => {
  updateBadge(data.count);
});
// 埋点模块
bus.on('cartUpdated', (data) => {
  analytics.track('add_to_cart', data.item);
});

现在,要加新功能只管bus.on,不用改购物车代码。Vue的emitter、React的useContext+useReducer其实都用了这个思想。

三、策略模式:消灭if-else毒瘤

场景:用户等级不同,商品折扣不同。你写了一个函数:

function getDiscount(level, price) {
  if (level === 'normal') return price * 0.95;
  else if (level === 'gold') return price * 0.9;
  else if (level === 'platinum') return price * 0.8;
  else return price;
}

这还好。但当你需要增加“钻石会员”、“企业会员”、“节日特惠”……函数越来越大,改一次心惊胆战。

策略模式解决:把算法抽成独立对象

const discountStrategies = {
  normal: (price) => price * 0.95,
  gold: (price) => price * 0.9,
  platinum: (price) => price * 0.8,
};
function getDiscount(level, price) {
  const strategy = discountStrategies[level];
  return strategy ? strategy(price) : price;
}

新增会员等级,只需要加一个策略,不用改getDiscount

更复杂的例子:表单验证

const validators = {
  required: (val) => val && val.trim() !== '',
  minLength: (val, len) => val.length >= len,
  email: (val) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val),
};
function validateField(value, rules) {
  for (let rule of rules) {
    const [name, param] = rule.split(':');
    const validator = validators[name];
    if (validator && !validator(value, param)) {
      return false;
    }
  }
  return true;
}
// 使用
const isValid = validateField('abc@test.com', ['required', 'email']);

以后增加“手机号验证”,加一个mobile策略即可,完全符合开闭原则(对扩展开放,对修改封闭)。

四、组合实战:一个购物车结算页面

  • 单例:全局唯一的购物车实例(存储商品列表)。
  • 观察者:商品数量变化时,触发价格重算、优惠券校验、埋点。
  • 策略:根据用户等级计算折扣;根据优惠券类型(满减、打折)计算优惠。
// 购物车单例
class Cart {
  static instance = null;
  static getInstance() {
    if (!Cart.instance) Cart.instance = new Cart();
    return Cart.instance;
  }
  items = [];
  addItem(item) {
    // 添加逻辑
    bus.emit('cartChanged', this.items);
  }
}
// 价格计算模块监听变化并应用折扣策略
bus.on('cartChanged', (items) => {
  const total = items.reduce((sum, item) => sum + item.price * item.count, 0);
  const discount = discountStrategies[user.level](total);
  renderTotal(discount);
});

各模块独立,改折扣策略不影响购物车;加埋点不影响价格计算。

五、总结:模式是工具,不是教条

  • 单例:保证全局唯一,适合共享资源。
  • 观察者:解耦事件发布和订阅,适合跨组件通信。
  • 策略:消除if-else,算法可互换,适合规则多变场景。

不要为了用模式而用模式。当你的代码出现重复、难维护、改一处动全身时,想想哪种模式能帮你“抽出来”。写代码就像搭积木,模式就是那些标准接口的积木块,让你搭得又快又稳。

❌
❌