news 2026/10/14 20:06:49

ESP8266搭建网络服务器:从零实现物联网最小闭环

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ESP8266搭建网络服务器:从零实现物联网最小闭环

1. 为什么一块几块钱的模块值得你花一晚上折腾

很多人第一次接触物联网,脑子里想的都是买一堆传感器、连上云平台、手机App远程控制,听起来很酷。但真到动手那一步,第一个卡住的地方往往不是传感器怎么接,而是数据怎么传出去。你手里那块开发板采集到了温湿度、光照、开关状态,可它怎么让手机或者电脑看到这些数据?答案就是网络服务器。

ESP8266 这块芯片在圈子里火了快十年了,价格便宜到离谱,某宝上十几块钱就能买到一块带 USB 转串口的开发板,核心芯片本身成本更低。它自带 Wi-Fi 功能,支持完整的 TCP/IP 协议栈,能独立跑一个轻量级网络服务器。换句话说,你不需要额外的路由器模块、不需要复杂的网络配置,一块 ESP8266 加上几行代码,就能让它在局域网里变成一个可以被浏览器访问的服务器。

这个项目的核心价值在于:它是物联网开发里最小可用的闭环。你不需要云平台、不需要 App、不需要复杂的鉴权体系,只要浏览器输入一个 IP 地址,就能看到设备状态、控制引脚电平。对于刚入门的人来说,这是理解“设备如何联网”“HTTP 请求怎么处理”“前后端怎么交互”最直观的方式。对于有经验的开发者来说,ESP8266 做网络服务器也是很多量产项目里的标准做法,比如智能插座、Wi-Fi 继电器、环境监测节点,底层逻辑完全一样。

我见过太多人卡在第一步:代码烧进去了,串口打印出 IP 地址了,但浏览器打不开。或者打开了,点按钮没反应。这些问题背后其实都是对网络服务器运行机制理解不到位。下面我会从整体设计思路开始,把每一步拆开讲清楚,包括那些文档里不会写的坑。

2. 整体方案设计与核心思路拆解

2.1 为什么选 ESP8266 而不是其他方案

市面上能做网络服务器的方案不少,常见的还有 ESP32、树莓派 Pico W、甚至用 Arduino 加以太网模块。ESP8266 的优势在于三点:成本极低、生态成熟、功耗可控。

成本方面,ESP8266 模组(比如 ESP-01S)单价可以做到十元以内,带开发板的版本也就十几到二十几块。相比之下 ESP32 贵一倍左右,树莓派 Pico W 更贵。对于只需要 Wi-Fi 联网和简单 GPIO 控制的项目,ESP8266 完全够用。

生态方面,Arduino 核心支持、NodeMCU 固件、MicroPython 都有成熟方案。社区里能搜到的例程、问答、踩坑记录非常多,遇到问题基本都能找到答案。这一点对新手特别重要,因为物联网开发里网络相关的问题排查门槛不低,有社区兜底会轻松很多。

功耗方面,ESP8266 在正常工作模式下大约 70mA 左右,深度睡眠可以做到 20μA 以下。如果你的项目是电池供电的传感器节点,这个特性很关键。当然做网络服务器的时候它需要持续在线,功耗会高一些,但相比树莓派那种动辄几百毫安的方案还是省很多。

2.2 网络服务器的两种实现路径

用 ESP8266 做网络服务器,实际上有两条路可以走。

第一条路是自己写 HTTP 服务器。在 Arduino 环境下,用ESP8266WebServer库,几十行代码就能起一个服务。你可以定义路由、处理 GET/POST 请求、返回 HTML 页面。这种方式灵活度最高,适合需要自定义接口、对接特定协议的场景。

第二条路是用现成的固件或平台。比如刷 NodeMCU 固件用 Lua 写,或者刷 Tasmota、ESPHome 这类现成固件,配置一下就能用。这种方式上手快,但定制能力受限,适合不想写代码、只想快速实现功能的场景。

这个项目我建议走第一条路,自己写代码。原因很简单:你要理解网络服务器到底是怎么回事,自己写一遍是最快的。而且后面如果要加传感器、加接口、改页面,自己写的代码改起来最顺手。

2.3 局域网服务器和公网访问的区别

这里要澄清一个概念。ESP8266 搭建的网络服务器默认是局域网服务器,也就是说只有连在同一个路由器下的设备才能访问。手机连的是家里 Wi-Fi,ESP8266 也连的是家里 Wi-Fi,它们在同一个网段里,所以能互相访问。

如果你想让外网也能访问,那就涉及到端口映射、内网穿透这些操作。这部分内容比较复杂,而且不同网络环境差异很大,这个项目先不展开。对于学习和大部分家用场景,局域网访问已经足够了。你人在家里,手机浏览器打开就能控制,不需要外网。

注意:局域网访问的前提是设备在同一个子网内。如果你的路由器开了 AP 隔离(也叫客户端隔离),同一 Wi-Fi 下的设备之间是互相 ping 不通的,这时候浏览器会打不开 ESP8266 的页面。遇到这种情况先去路由器设置里把 AP 隔离关掉。

2.4 整体数据流梳理

把整个系统的数据流画清楚,后面写代码就不会乱。

上电之后,ESP8266 先执行初始化:配置串口波特率、设置 GPIO 模式、连接 Wi-Fi。连接成功后,串口会打印出分配到的 IP 地址。然后启动 HTTP 服务器,监听 80 端口。这时候浏览器发起请求,ESP8266 收到请求后根据 URL 路径决定返回什么内容:访问根路径返回控制页面,访问/led/on执行开灯操作,访问/status返回当前状态 JSON。

整个过程中,ESP8266 既是服务器又是执行器。它接收 HTTP 请求,解析请求内容,执行对应操作,然后返回响应。浏览器端就是一个普通的网页,用 JavaScript 发请求、更新界面。这个架构和传统的 Web 开发本质一样,只是服务器从电脑换成了单片机。

3. 核心细节解析与实操要点

3.1 硬件选型与接线要点

ESP8266 开发板常见的有几种:NodeMCU、Wemos D1 mini、ESP-01S 配转接板。新手我推荐 NodeMCU 或 Wemos D1 mini,因为它们自带 USB 转串口芯片,一根 Micro USB 线就能供电和烧录,不需要额外接 FTDI 模块。

接线方面,如果你只是做网络服务器加一个 LED 控制,其实不需要额外接线。开发板上自带一个 LED,通常接在 GPIO2 上(不同板子可能不一样,看丝印)。但板载 LED 通常用来指示状态,拿来做实验可以,做实际项目建议外接一个 LED 到空闲 GPIO。

外接 LED 的接法:LED 正极串联一个限流电阻(220Ω 到 1kΩ 都可以),接到 GPIO 引脚,负极接 GND。电阻的作用是限制电流,防止烧坏 LED 或 GPIO。ESP8266 的 GPIO 输出电流能力有限,单个引脚建议不超过 12mA,所以电阻不要太小。

注意:ESP8266 的 GPIO 工作电压是 3.3V,不是 5V。如果你接 5V 的传感器或模块,一定要确认它有电平转换,否则可能烧坏芯片。这个问题在接继电器模块、显示屏的时候特别常见。

3.2 开发环境搭建的关键选择

开发环境有两种主流选择:Arduino IDE 和 PlatformIO。

Arduino IDE 胜在简单,装好之后在首选项里添加 ESP8266 的板管理地址,然后在板管理器里搜索安装,就能选到 NodeMCU 等板型。适合快速验证、写小 demo。

PlatformIO 是 VS Code 的插件,项目管理更规范,库依赖用配置文件管理,编译速度也快一些。适合项目稍微复杂一点、需要版本管理的场景。

我个人的习惯是:验证想法用 Arduino IDE,正式项目用 PlatformIO。这个项目两种都行,下面代码以 Arduino 环境为例,PlatformIO 用户把库依赖写进platformio.ini即可。

安装 ESP8266 支持包的步骤:打开 Arduino IDE,文件 -> 首选项 -> 附加开发板管理器网址,填入http://arduino.esp8266.com/stable/package_esp8266com_index.json,然后工具 -> 开发板 -> 开发板管理器,搜索esp8266安装。安装完成后在开发板列表里选NodeMCU 1.0 (ESP-12E Module)或对应的板型。

3.3 核心库的选择与作用

这个项目主要用到两个库:ESP8266WiFi和ESP8266WebServer。

ESP8266WiFi负责 Wi-Fi 连接管理,提供WiFi.begin()、WiFi.status()、WiFi.localIP()这些方法。它是 ESP8266 Arduino 核心自带的,不需要额外安装。

ESP8266WebServer负责 HTTP 服务器功能,提供路由注册、请求处理、响应发送。同样自带,不需要额外安装。

如果你需要返回 JSON 格式的数据,可以用ArduinoJson库来序列化和反序列化。这个库需要额外安装,在库管理器里搜索ArduinoJson即可。对于简单项目,手动拼接 JSON 字符串也行,但用库更规范,不容易出错。

3.4 网络配置的注意事项

Wi-Fi 连接这块有几个细节容易出问题。

第一,ESP8266 只支持 2.4GHz 频段,不支持 5GHz。如果你的路由器同时开了 2.4G 和 5G,确保 ESP8266 连的是 2.4G 那个 SSID。很多新手在这里卡很久,代码没问题,就是连不上,最后发现是连了 5G 的 Wi-Fi。

第二,Wi-Fi 名称和密码不要有特殊字符。虽然理论上支持,但实际测试中,包含中文、空格、特殊符号的 SSID 或密码有时会导致连接失败。建议先用简单的英文加数字组合测试。

第三,连接超时处理。WiFi.begin()之后不要死等,要加超时判断。如果连不上,串口打印提示,然后重启或者进入配网模式。死等的代码会让设备看起来像死机了一样。

第四,静态 IP 和动态 IP 的选择。默认是 DHCP 动态获取 IP,每次重启可能不一样。如果你希望每次都是同一个 IP,方便浏览器收藏,可以设置静态 IP。但要注意静态 IP 不能和路由器网段冲突,也不能和其他设备冲突。

4. 完整实操过程与核心代码实现

4.1 第一步:让 ESP8266 连上 Wi-Fi

先写一个最小程序,验证 Wi-Fi 连接是否正常。这一步不涉及服务器,只确认网络通了。

#include <ESP8266WiFi.h> const char* ssid = "你的Wi-Fi名称"; const char* password = "你的Wi-Fi密码"; void setup() { Serial.begin(115200); delay(100); Serial.println(); Serial.print("正在连接 Wi-Fi: "); Serial.println(ssid); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); unsigned long startTime = millis(); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); if (millis() - startTime > 20000) { Serial.println(); Serial.println("连接超时,请检查 Wi-Fi 名称和密码"); return; } } Serial.println(); Serial.println("连接成功"); Serial.print("IP 地址: "); Serial.println(WiFi.localIP()); } void loop() { // 这里先空着 }

烧录之后打开串口监视器,波特率选 115200。正常的话你会看到一串点之后打印出 IP 地址,类似192.168.1.100。记下这个地址,后面浏览器要用。

如果一直打印点然后超时,按顺序排查:Wi-Fi 名称密码是否正确、是不是 2.4G 频段、路由器是否开了 MAC 过滤、信号强度是否够。可以先把开发板放到路由器旁边测试。

4.2 第二步:搭建最简 HTTP 服务器

Wi-Fi 通了之后,加上服务器代码。下面是一个最简版本,访问根路径返回一句问候。

#include <ESP8266WiFi.h> #include <ESP8266WebServer.h> const char* ssid = "你的Wi-Fi名称"; const char* password = "你的Wi-Fi密码"; ESP8266WebServer server(80); void handleRoot() { server.send(200, "text/plain; charset=utf-8", "你好,这是 ESP8266 服务器"); } void setup() { Serial.begin(115200); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(); Serial.print("IP: "); Serial.println(WiFi.localIP()); server.on("/", handleRoot); server.begin(); Serial.println("HTTP 服务器已启动"); } void loop() { server.handleClient(); }

关键点在于server.handleClient()必须放在loop()里不断调用。它的作用是检查有没有新的请求进来,有的话就处理。如果你在loop()里写了delay(1000)或者长时间阻塞的操作,服务器响应会变慢甚至无响应。这是新手最常见的错误之一。

烧录后浏览器输入串口打印的 IP 地址,应该能看到那句问候。如果打不开,先确认手机或电脑和 ESP8266 在同一个 Wi-Fi 下,然后 ping 一下那个 IP 看通不通。

4.3 第三步:加入 GPIO 控制功能

现在加入 LED 控制。定义两个路由:/led/on开灯,/led/off关灯。同时把根路径改成一个带按钮的 HTML 页面。

#include <ESP8266WiFi.h> #include <ESP8266WebServer.h> const char* ssid = "你的Wi-Fi名称"; const char* password = "你的Wi-Fi密码"; const int ledPin = 2; // 板载 LED 通常在 GPIO2 ESP8266WebServer server(80); String getPage() { String html = "<!DOCTYPE html><html><head><meta charset='utf-8'>"; html += "<meta name='viewport' content='width=device-width, initial-scale=1'>"; html += "<title>ESP8266 控制面板</title></head><body>"; html += "<h1>ESP8266 网络服务器</h1>"; html += "<p>当前 LED 状态: <span id='state'>未知</span></p>"; html += "<button onclick=\"fetch('/led/on').then(updateState)\">开灯</button>"; html += "<button onclick=\"fetch('/led/off').then(updateState)\">关灯</button>"; html += "<script>"; html += "function updateState(){fetch('/status').then(r=>r.text()).then(t=>{document.getElementById('state').innerText=t;});}"; html += "updateState();"; html += "</script></body></html>"; return html; } void handleRoot() { server.send(200, "text/html; charset=utf-8", getPage()); } void handleLedOn() { digitalWrite(ledPin, LOW); // 板载 LED 低电平点亮 server.send(200, "text/plain", "LED 已开启"); } void handleLedOff() { digitalWrite(ledPin, HIGH); server.send(200, "text/plain", "LED 已关闭"); } void handleStatus() { String state = (digitalRead(ledPin) == LOW) ? "开启" : "关闭"; server.send(200, "text/plain; charset=utf-8", state); } void setup() { Serial.begin(115200); pinMode(ledPin, OUTPUT); digitalWrite(ledPin, HIGH); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(); Serial.print("IP: "); Serial.println(WiFi.localIP()); server.on("/", handleRoot); server.on("/led/on", handleLedOn); server.on("/led/off", handleLedOff); server.on("/status", handleStatus); server.begin(); Serial.println("服务器启动完成"); } void loop() { server.handleClient(); }

这里有几个细节值得说。板载 LED 的接法通常是阳极接 3.3V,阴极接 GPIO,所以digitalWrite(LOW)是点亮,HIGH是熄灭。如果你外接 LED 是 GPIO 接阳极、阴极接 GND,那逻辑就反过来。写代码前先用万用表或者看板子原理图确认一下。

页面里的 JavaScript 用了fetch来发请求,这是现代浏览器都支持的方式。点击按钮后发一个 GET 请求,服务器执行操作并返回结果,然后updateState再请求一次/status更新显示。这个流程就是最基础的异步交互。

4.4 第四步:优化响应速度和稳定性

上面代码能跑,但有几个地方可以优化。

第一,把 HTML 页面放到PROGMEM里。ESP8266 的 RAM 比较小,大段字符串放在 RAM 里会占用宝贵空间。用PROGMEM存到 Flash 里,可以省出 RAM 给其他功能。对于简单页面差别不大,但页面复杂了之后很有必要。

第二,给服务器加请求超时和错误处理。ESP8266WebServer默认对未注册的路径返回 404,但你可以自定义 404 页面,让体验更好。

第三,如果控制指令比较多,建议用 POST 而不是 GET。GET 请求的参数会出现在 URL 里,容易被浏览器缓存或历史记录泄露。POST 更适合执行操作类请求。不过对于家用局域网控制,GET 的简单性优势更大,看个人取舍。

第四,加一个看门狗或者定时重启机制。ESP8266 长时间运行偶尔会遇到内存碎片或者网络异常,导致服务器无响应。可以在loop()里判断 Wi-Fi 状态,如果断开了就尝试重连。也可以每隔几天自动重启一次,保持稳定。

void checkWiFi() { if (WiFi.status() != WL_CONNECTED) { Serial.println("Wi-Fi 断开,尝试重连"); WiFi.disconnect(); WiFi.begin(ssid, password); unsigned long start = millis(); while (WiFi.status() != WL_CONNECTED && millis() - start < 10000) { delay(500); } if (WiFi.status() == WL_CONNECTED) { Serial.print("重连成功,IP: "); Serial.println(WiFi.localIP()); } } }

把这个函数放到loop()里,每隔几秒调用一次,能解决大部分网络掉线问题。

4.5 第五步:扩展传感器数据展示

网络服务器不只是控制,也可以展示数据。假设你接了一个 DHT11 温湿度传感器,可以把读数显示在页面上。

#include <DHT.h> DHT dht(4, DHT11); // GPIO4 接 DHT11 数据脚 void handleSensor() { float h = dht.readHumidity(); float t = dht.readTemperature(); if (isnan(h) || isnan(t)) { server.send(500, "text/plain", "传感器读取失败"); return; } String json = "{\"temperature\":" + String(t) + ",\"humidity\":" + String(h) + "}"; server.send(200, "application/json", json); }

然后在页面里用 JavaScript 定时请求/sensor,把数据更新到界面上。这样就形成了一个完整的监测加控制闭环。DHT11 的库需要额外安装,在库管理器里搜索DHT sensor library即可。

注意:DHT11 读取间隔不能太短,官方建议至少 2 秒一次。如果你在loop()里不停地读,会读到错误数据。正确做法是用millis()做时间判断,每 2 秒以上读一次。

5. 常见问题与排查技巧实录

5.1 浏览器打不开页面怎么办

这是最高频的问题。排查顺序如下:

现象可能原因解决方法
串口没打印 IPWi-Fi 没连上检查 SSID 密码、频段、信号
有 IP 但 ping 不通不在同一网段或 AP 隔离确认设备同 Wi-Fi,关闭 AP 隔离
ping 通但浏览器超时端口被占用或服务器没启动确认server.begin()已调用
页面加载一半卡住loop()里有阻塞操作移除delay()和长循环
偶尔能开偶尔不能Wi-Fi 信号弱或内存不足靠近路由器,优化代码

我遇到过最隐蔽的一次是路由器开了 IPv6,ESP8266 获取到的是 IPv4 地址,但电脑优先走 IPv6 解析,导致访问异常。解决办法是在电脑网络设置里临时禁用 IPv6,或者直接用 IP 地址访问而不是主机名。

5.2 按钮点了没反应

如果页面能打开,但点按钮没反应,先看串口有没有打印请求日志。没有日志说明请求根本没到 ESP8266,可能是 JavaScript 报错了。打开浏览器开发者工具(F12)看 Console 有没有红色错误。

常见原因是fetch的路径写错了,或者页面里的引号嵌套有问题。上面代码里 HTML 字符串用了单引号包属性,双引号包 JavaScript 字符串,这个嵌套关系要仔细检查。另一个原因是浏览器缓存了旧页面,按 Ctrl+F5 强制刷新试试。

5.3 服务器运行一段时间后无响应

ESP8266 长时间运行后无响应,通常是两个原因:内存泄漏或者 Wi-Fi 断连。

内存泄漏方面,避免在loop()里频繁创建String对象。String用多了会产生内存碎片,最终导致分配失败。可以用字符数组代替,或者把固定字符串放到PROGMEM。

Wi-Fi 断连方面,加上前面说的checkWiFi()函数,定期检查重连。另外可以在loop()里加一个计数器,每执行多少次就重启一次,比如每 24 小时重启。虽然粗暴,但很有效。

unsigned long lastRestart = 0; const unsigned long restartInterval = 86400000UL; // 24小时 void loop() { server.handleClient(); checkWiFi(); if (millis() - lastRestart > restartInterval) { ESP.restart(); } }

5.4 烧录失败或板子不识别

烧录失败常见原因:USB 线是充电线不是数据线、驱动没装、板型选错、端口被占用。

先换一根确认能传数据的 USB 线。然后在设备管理器里看有没有识别到串口芯片,NodeMCU 通常用 CP2102 或 CH340,需要装对应驱动。板型在工具菜单里选对,NodeMCU 选NodeMCU 1.0,Wemos D1 mini 选LOLIN(WEMOS) D1 mini。如果端口灰色不可选,拔插一下 USB 或者重启 IDE。

还有一个坑:有些 ESP8266 板子需要手动进入烧录模式,按住 FLASH 按钮再按 RST 按钮,然后松开。不过大部分带 USB 转串口的开发板都支持自动下载,不需要手动操作。

5.5 实操心得与避坑清单

做了几个 ESP8266 项目之后,我总结了下面这些经验,都是文档里不会写的:

  • 串口打印是你的第一调试工具。每个关键步骤都加Serial.println(),出问题时看串口输出比瞎猜快十倍。
  • 不要用delay()做长时间等待。需要延时用millis()做非阻塞判断,否则服务器会卡死。
  • GPIO 编号和板子丝印编号不是一回事。代码里用的是 GPIO 编号,板子上印的可能是 D1、D2 这种,要对照引脚图。
  • 供电要足。ESP8266 发射 Wi-Fi 瞬间电流能到 300mA 以上,如果 USB 口供电不足,会不断重启。用质量好的 USB 线,或者外接 3.3V 稳压电源。
  • 天线朝向有影响。板载 PCB 天线对方向敏感,尽量让天线区域远离金属和电池。
  • 代码里不要硬编码 Wi-Fi 密码然后上传到公开仓库。可以用secrets.h单独存放,或者用配网模式让用户自己输入。
  • 测试的时候先用手机热点,排除路由器兼容性问题。有些老路由器对 ESP8266 的 Wi-Fi 兼容性不好,换热点就正常了。

5.6 性能边界与适用场景判断

ESP8266 做网络服务器有它的能力边界,心里要有数。

它能稳定支撑的场景:同时 1 到 3 个客户端访问、页面大小几十 KB 以内、请求频率每秒几次、控制指令简单。家用智能开关、传感器数据展示、小型控制面板,这些都没问题。

它撑不住的场景:高并发访问、大文件传输、复杂的前后端交互、需要 HTTPS 的场景。ESP8266 的 RAM 只有几十 KB,处理能力有限,HTTPS 握手会消耗大量资源,实际项目中很少用它做 HTTPS 服务器。

如果你需要更强的性能,升级到 ESP32 是自然的选择。ESP32 双核、RAM 更大、支持蓝牙和更多外设,代码结构基本兼容,迁移成本不高。但作为入门第一步,ESP8266 足够让你把网络服务器的核心概念摸透。

我个人在实际操作中的体会是,ESP8266 最大的价值不是它有多强,而是它足够简单。你花一个晚上就能从零搭出一个能用的网络服务器,这种即时反馈对学习物联网特别重要。后面再学 MQTT、云平台对接、OTA 升级,底层逻辑都是从这个最小闭环延伸出去的。把这一步走扎实,后面的路会顺很多。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 20:06:45

CentOS 7 Samba 配置三重校验:SELinux、firewalld、smbpasswd 实战避坑指南

简介&#xff1a;本资源是一份面向Linux系统管理员与运维工程师的CentOS 7 Samba服务器实战配置指南&#xff0c;聚焦局域网文件共享服务部署中的核心场景——匿名访问与身份验证双模式配置。内容覆盖Samba服务安装、smb.conf精细化配置&#xff08;含全局参数与共享段定义&…

作者头像 李华
网站建设 2026/10/14 20:06:00

Kaggle高手为何难进工业界?三大能力断层解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/14 20:03:33

区间DP从入门到进阶:状态设计、转移框架与经典模型详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/14 20:02:22

React Native鸿蒙实践:直播购物场景的流式渲染与手势交互优化

直播购物这类应用&#xff0c;大概是移动端里交互最“挤”的场景之一&#xff1a;上面在播视频&#xff0c;中间在刷评论&#xff0c;底部在滚商品&#xff0c;用户还随时可能上滑进下一个直播间、下拉打开详情弹层。要把这套体验在鸿蒙设备上做出来&#xff0c;还要保持跨平台…

作者头像 李华
网站建设 2026/10/14 20:02:02

模型压缩四大路线实战:剪枝、量化、蒸馏与AutoML选型指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/14 20:01:51

Vue 3 + Vuelidate 自定义必传校验实战:从原理到避坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华