React useEffect 从入门到进阶:依赖数组、清理函数与闭包陷阱全解析

发布时间:2026/10/6 21:44:47

React useEffect 从入门到进阶:依赖数组、清理函数与闭包陷阱全解析 拿useEffect当“刷新键”来用之前先想清楚这其实是一张通向React外部世界的门票。很多同学第一次接触这个Hook的时候都会觉得它像周公解梦一样神奇“我明明没写任何调用逻辑怎么页面一变这个函数就自己跑了”这种“自动刷新世界”的体验确实让人上头但等你在生产环境被它坑过几次之后就会发现useEffect真正的名字应该叫“副作用管理”它把所有和React渲染无关的活都接了下来发请求、订阅事件、操作DOM、埋点上报、启动定时器。这篇文章我会用多年踩坑换来的经验把这个Hook从原理到实战彻底讲透适合刚学完React基础但每次写useEffect都没底的同学也适合已经写了两三年React却总是被依赖数组折磨的资深开发。1. 内容整体设计与思路拆解1.1 useEffect到底解决的是什么问题React组件的核心职责是“根据状态渲染UI”但真实的页面永远不只有UI。你要在组件挂载后去后端拉一次列表数据你要在某个状态变化时给第三方统计平台发一条埋点你要在弹窗打开时给document注册一个键盘监听——这些操作有一个共同点它们都不能直接写在渲染过程里因为React的渲染函数必须是纯函数一旦在里面偷偷改了状态或者碰了浏览器API轻则触发额外的重复渲染重则直接把整个应用跑崩。useEffect就是React官方给出来的、专门承载这些“非渲染工作”的通道。它接受两个参数第一个是effect回调函数里面写你要执行的副作用逻辑第二个是依赖数组deps告诉React“什么时候该重新执行这个回调”。这两个参数组合起来就让React有了一个可以精确控制的“刷新”机制每当依赖数组里的某个值发生变化React就会在DOM更新完成之后重新执行一遍回调函数。这里的关键认知是useEffect不是用来“响应状态变化”的函数而是用来“同步外部系统”的通道。如果你的逻辑只是“根据A状态计算B状态”那你应该用useMemo或者直接在渲染期计算而不是塞进useEffect——我曾经见过一个同事把所有状态联动都写成useEffect结果一个页面挂了十多个effect每次数据变化都经过好几轮“更新-触发effect-再更新”的循环最后性能惨不忍睹代码也没法维护。1.2 为什么说依赖数组才是真正的“刷新开关”很多人把useEffect当成“每次渲染都跑一遍的东西”这其实只对了一半。默认情况下也就是第二个参数完全不传的时候useEffect确实会在组件每次渲染完成后都执行。但实战中绝大多数场景都不需要这么高的频率所以你需要在依赖数组里告诉React只在这些东西变了才跑。打个比方你家里养了一条特别警觉的看门狗如果它听到任何动静都叫每次渲染都执行你一整晚都别想睡。依赖数组就像是给你这条狗设定“只在敲门声响起时叫”的训练规则。组件挂载后首次渲染会执行一次相当于狗第一天上班先熟悉一下环境之后只有当依赖数组里的项发生变化时effect才会再次触发。传一个空数组[]则表示“只在挂载时跑一次之后什么都不管了”。但这里有个新手最容易踩的坑依赖数组的比较是浅比较用的是Object.is。如果你把一个对象字面量写进依赖数组比如{ id: 1 }那React每次渲染拿到的都是一个新的引用Object.is判断两个对象不相等effect就会无限循环。这个问题我后面会用一整节来讲因为它真的是生产环境最常见的线上事故来源。1.3 从组件生命周期模型到状态同步模型React 16.8之前老开发者习惯了三个生命周期方法componentDidMount、componentDidUpdate、componentWillUnmount。useEffect把这三个方法的能力统一到了一个API里通过依赖数组控制执行时机通过在effect里返回清理函数对应componentWillUnmount。我刚开始带团队的时候总有人问我“那useEffect到底对应挂载、更新还是卸载”我的回答是它一个都不对应它对标的是“与外部世界的同步关系”。你想想一次effect完整执行包含两个阶段跑副作用逻辑 执行上一次遗留的清理函数。这就意味着React在渲染结束后不是简单地说“该刷新了”而是先“打扫战场”再“布置新战场”。理解了这个模型你才能写出正确的取消请求、移除监听、清除定时器的代码。2. 核心细节解析与实操要点2.1 依赖数组的五种写法每一种都对应一种业务依赖数组的写法表面上只有“传/不传/传空”三种情况但实际组合起来至少有五种常见用法我把它们整理成一张表写法执行时机典型场景不传第二个参数每次渲染后都执行几乎不使用了解即可[]挂载完成后执行一次初始化拉取列表、注册全局监听[a, b]a或b变化时执行输入联动、筛选条件变化后重新请求依赖项是props里的函数props函数引用变化时执行父组件传递给子组件的回调逻辑依赖项是ref.current通常无效需要读取最新DOM时用回调ref替代第一眼看上去传一个空数组好像最省事副作用只跑一次但你要小心如果在副作用里引用了props或者state那它们只会被初始值闭包捕获以后永远拿不到新值。这就是React社区著名的“闭包陷阱”。举个实战例子你有一个详情页挂载时发请求请求体里要用到props.userId。如果依赖数组写成[]那所有逻辑里用到的userId都是第一次渲染时的旧值。后来用户切换了账号页面组件没有重新挂载effect也不会再执行界面上的数据永远是上一个用户的。这种情况正确写法是把props.userId放进依赖数组。如果你确实只想在挂载时执行一次又需要用到最新值那就得借助useRef来绕过闭包问题——这个方案后面会细讲。2.2 清理函数的三类用途监听、定时器、异步请求React官网有一个关键词叫cleanup很多人直接忽略它觉得useEffect能跑就行。但在真实项目中不写清理函数的后果通常是内存泄漏、事件重复触发、请求结果竞态。第一类是事件监听。弹窗组件挂载时给document绑定了keydown如果关闭时不解除监听每开一次弹窗就多绑一个监听器键盘事件就会触发N次逻辑而且用户关掉弹窗后按方向键页面还能莫名其妙地滚动。清理函数里必须写document.removeEventListener而且要确保传入的处理器函数是同一个引用——这就是为什么我建议你在effect内部定义函数而不要在外面定义再引用容易因为闭包不同导致解绑失败。第二类是定时器。搜索框防抖是最经典的例子用户连续输入时每次按键都会清掉上一个定时器并重新计时。如果不清理上一次定时器到期后照样会发出请求你就看到一连串没用的网络请求发出去。在清理函数里clearTimeout才能保证只有最后一次停留满300毫秒的输入才会真正触发请求逻辑。第三类是异步请求的竞态。这是最阴间的坑之一你发了一个请求数据还没回来用户又切换了筛选条件第二次请求发出去了结果第一次请求先返回把第二次的结果覆盖掉了。解决方法是每次effect执行时用一个let cancelled false标记在清理函数里把它设为true然后异步回调拿到数据后先判断这个标记如果已经取消就直接丢弃结果。useEffect(() { let cancelled false; fetch(/api/list?page${page}) .then(res res.json()) .then(data { if (!cancelled) { setList(data); } }); return () { cancelled true; }; }, [page]);这段代码看起来平平无奇但它真正实现了“只接受最新一次请求的结果”。我把它称为“卑微的取消标记”因为JavaScript里的fetch根本没有真正的取消机制AbortController虽然可以中断请求但很多接口和中间层处理得并不好反而是这种标记法在各种场景下都非常稳。2.3 为什么在effect里修改外部变量常常无效新手经常写这样的代码在useEffect里给一个全局变量赋值或者修改一个let声明的局部变量然后发现UI根本没有变。原因很简单useEffect里做的操作React并不可知。你改了局部的let temp 0React不知道你改了全局数组window.list.push(item)React也不知道。只有通过setState触发的新渲染React才能看到变化。这不是useEffect的问题而是React数据流方向的问题。React希望你始终用“状态驱动”的思维先把值放到state里然后React负责重新渲染渲染结果里所有东西都从state派生。如果直接把值塞进useEffect你就绕过了React的调度系统副作用成功执行了UI却不会响应。我自己的经验法则是能在渲染期算出来的就不放useEffect非要在effect里做的一定要以setState收尾。比如根据一个搜索参数去请求数据请求结果必须放进state但如果你只是想根据参数拼接一个跳转链接直接在渲染里算就行完全没有必要引入effect。3. 实操过程与核心环节实现3.1 第一个能跑的完整流程一个带防抖的搜索页面说再多理论不如直接写一个项目里最常见的例子搜索框实时请求。我把步骤拆给你看每一步我会标注“为什么”。第一步先定义搜索关键字state和一个保存结果的列表statefunction SearchBox() { const [keyword, setKeyword] useState(); const [results, setResults] useState([]); const [loading, setLoading] useState(false);第二步写useEffect依赖数组放keyword。这里如果直接放keyword用户每敲一个字母就会发一次请求很浪费。所以我先给关键字做一个300毫秒的防抖处理。这一步我通常用useRef配合useState而不是简单地在effect里setTimeout因为单独写定时器的话每次渲染都会创建新的闭包环境特别容易乱const [debouncedKeyword, setDebouncedKeyword] useState(keyword); useEffect(() { const timer setTimeout(() { setDebouncedKeyword(keyword); }, 300); return () clearTimeout(timer); }, [keyword]);第三步是真正的请求effect依赖数组放debouncedKeyword。这个设计保证了只有用户停止输入300毫秒之后才会发出请求而且effect内部通过清理函数解决了竞态问题useEffect(() { if (!debouncedKeyword.trim()) { setResults([]); return; } let cancelled false; setLoading(true); fetch(/api/search?q${encodeURIComponent(debouncedKeyword)}) .then(res res.json()) .then(data { if (!cancelled) { setResults(data.list); } }) .finally(() { if (!cancelled) { setLoading(false); } }); return () { cancelled true; }; }, [debouncedKeyword]);看到没有两个useEffect各司其职一个负责搬砖一个负责砌墙。第一个effect把原始的keyword降频成debouncedKeyword第二个effect只在降频后的值变化时才真正发请求。这种写法在团队代码评审的时候很容易过因为逻辑边界非常清晰。3.2 effect执行顺序与生命周期节点的对应关系使用React 18以后严格模式默认会在开发环境里让effect执行两次挂载→清理→再挂载。第一次见到这个现象的同学们不要慌这不是bug这是React故意暴露潜在问题的机制。它逼迫你把清理函数写得足够健壮如果你的effect秒挂秒清之后还能正常运行那说明代码没有泄漏。很多没经验的同学在这里被吓到以为是自己setState死循环结果排查半天发现问题出在“开发环境双调用”上。生产环境里effect的执行顺序是固定的组件渲染完成后React会按照useEffect在代码中出现的顺序依次执行每个effect的清理函数则会在下一次effect执行之前统一清理一遍。换句话说React不是“边执行边清理”而是“先把上一轮的旧账全部结清再开新一轮”。这个概念很重要因为如果你在effect A里修改了effect B依赖的值那B会在A跑完后的这一轮正常触发但如果你在effect A的清理函数里修改了B依赖的值就可能引发一些难以察觉的连锁反应。3.3 依赖数组里放函数时的常见处理方案在React里写函数组件久了你会发现一个尴尬的问题父组件传给子组件的函数如果每次渲染都重新定义那么子组件里useEffect只要依赖了这个函数就会在父组件每次渲染后都重新执行。解决办法有几种我按推荐程度排序第一如果函数只是父组件内部用的就不应该传进useEffect的依赖数组你可以在effect内部直接调用不需要放到依赖里只要确保effect内部用到的props和state都列全就行。不过我一般会避免这个做法因为ESLint插件会强烈报警告。第二使用useCallback包裹函数让它在依赖不变的条件下保持引用稳定。比如父组件有个handleSearch函数里面只依赖pageSize这个state那你用useCallback(() { ... }, [pageSize])包一圈子组件useEffect把handleSearch放进依赖数组就可以做到只有pageSize变化时才重新触发。第三如果函数真的足够“纯”也就是不依赖任何可变值那可以直接在组件外部定义全局只有一份引用放进依赖数组永远不会造成额外触发。真实项目中我最常用的是useCallback方案。虽然多写几行字但它在避免无效effect触发的同时也让子组件可以放心地用React.memo做渲染优化。如果你的代码里到处都是“每次渲染都重新创建的函数”那别说useEffect了整个应用的性能都要打个问号。4. 常见问题与排查技巧实录4.1 无限循环依赖数组里的对象引用陷阱这是我在各个技术群里回答次数最多的问题“为什么我的useEffect疯狂请求接口”十次有八次是依赖数组里放了对象或数组。举个例子useEffect(() { fetchData({ filters: filters }); }, [filters]);如果filters来自props或者useState它本身可能是个稳定引用那没问题。但如果你写的是{ name: keyword }这种字面量React每次渲染都创建一个全新的对象Object.is比较永远不相等effect就会无限循环。很多人一开始想不通值明明一样啊为什么React说它变了原因就是引用相等性。两个对象哪怕内部的每一个属性都相同只要不是同一个引用Object.is就返回false。我在排查这个问题的时候会先让同事把依赖数组里的对象拆开改成原始类型的属性比如[filters.name, filters.date]这样引用比较就变成值比较循环立刻停止。如果对象本身确实需要整体传递就考虑用useMemo把它缓存起来保证依赖不变时返回同一个引用。4.2 闭包陷阱为什么effect里拿到的state总是旧值闭包陷阱是另一个高频问题。核心场景是在useEffect里实现一个定时器每秒打印一次某个state的值结果发现打印出来的永远是初始值。看起来像是useEffect没有被刷新实际上是你创建定时器时闭包捕获了那一轮的state而定时器执行的时候用的还是旧闭包。解决方法有三种我按推荐顺序列出用useRef保存最新值。把state放到ref里每次渲染时用effect把它同步一下然后定时器逻辑里读ref.current永远拿到最新值。const countRef useRef(0); countRef.current count; // 这一行必须在组件渲染期执行 useEffect(() { const timer setInterval(() { console.log(countRef.current); }, 1000); return () clearInterval(timer); }, []);把state放进依赖数组并重新创建定时器。这样每次count变化都会重建定时器虽然逻辑简单但如果定时器中断/重启成本高就不太合适。用useReducer把逻辑封装起来让 reducer根据action计算新状态避免在effect内部读state。我个人最常用第一种。注意countRef.current count要在渲染期执行而不是在effect里执行因为effect执行时机比较晚可能在定时器已经启动之后才会更新ref导致第一轮打印的还是旧值。4.3 如何在effect里只取最新值但不想每次重新执行这个问题很多人绕了很久。需求往往是因为某个副作用太昂贵我不想让它在某个state变化时重新执行但我又必须在定时器或者事件回调里拿到这个state的最新值。答案就是useRef方案渲染期把state同步给refeffect的依赖数组保持为空回调里只读ref。用这种方式你既享受了“只跑一次”的轻量又不会遇到闭包陷阱。但这里有个重要前提ref的同步必须在渲染期完成。如果你在useEffect里赋值countRef.current count那么这个赋值发生在DOM提交之后而你的定时器如果已经在useEffect里启动了那一轮定时器读取ref时ref还没来得及更新。所以我总是把ref同步放在组件函数体的第一层也就是和state声明并列的位置而不是塞在某个effect里。4.4 ESLint的exhaustive-deps规则要不要关掉这个话题我在团队里没有少吵过。React官方提供的react-hooks/exhaustive-deps插件强制要求effect里用到的变量全部出现在依赖数组里。很多开发者嫌它烦直接关掉或者把数组写成[]硬扛。我的建议非常简单不要关但也不要无脑满足它。这条规则本质是让你正视effect和外部变量之间的关系。如果你把某个变量写进effect却故意不放依赖数组ESLint会提醒你这时候你该反思的是“我为什么要在effect里读一个我不打算响应它的值”。如果确实需要这么干方案是改成ref或者用官方的useEventReact 19里有相关调整思路来解决。如果你只是靠注释// eslint-disable-line压掉警告那其实就是埋了一颗地雷等到哪天需求变更、代码路径变了闭包陷阱就爆了。5. 场景化应用与扩展实战5.1 路由参数变化时重新拉详情数据页面详情是useEffect最典型的应用场景之一。你有一个/user/:id路由用户从列表页点进来组件挂载后按id请求详情。用户如果继续点击“下一个用户”组件不会重新挂载但路由参数变了这时候你的useEffect必须订阅这个变化。关键点是依赖数组里不能只写props.match.params.id就完事了你要想清楚请求的完整链路。如果详情数据里还依赖一个locale那它也得进依赖数组。否则用户在切换语言时不会重新请求展示的还是旧语言的数据。useEffect(() { setLoading(true); fetchUser(id).then(user { setUser(user); }).finally(() setLoading(false)); }, [id, locale]);这里有一个我踩过很多次的细节不要在useEffect里把setLoading(false)写在then外面否则请求失败时loading状态可能卡在true。要放在finally里并且用清理标记保护setState调用。5.2 自定义Hook封装把逻辑喂给任意组件useEffect最强大的用法是作为自定义Hook的底层零件。比如我把“请求列表”这个通用逻辑抽成useFetchListfunction useFetchList(url, params) { const [data, setData] useState([]); const [loading, setLoading] useState(true); const [error, setError] useState(null); useEffect(() { let cancelled false; setLoading(true); fetch(${url}?${new URLSearchParams(params)}) .then(res res.json()) .then(result { if (!cancelled) { setData(result); setError(null); } }) .catch(err { if (!cancelled) { setError(err); } }) .finally(() { if (!cancelled) { setLoading(false); } }); return () { cancelled true; }; }, [url, JSON.stringify(params)]); // 注意url和params的引用需要稳定一般由调用方用useMemo/useCallback保证 return { data, loading, error }; }这里面的细节值得多说一句依赖数组里我故意用了JSON.stringify(params)这样对象属性值没变时effect不会重新触发。但这个方法有明显缺点JSON.stringify本身有性能开销且对象属性顺序变化也会造成误判。生产环境我更推荐用useMemo对外部传入的params做缓存不到万不得已不考虑字符串化方案。5.3 和useLayoutEffect的边界划分很多开发者知道有useLayoutEffect但从来分不清什么时候该用哪个。一句话说明白useEffect在DOM变更后异步执行用户在浏览器绘制内容之前看不到它useLayoutEffect则是在DOM变更后同步执行可以拿到真实的布局信息后再动手但会阻塞浏览器绘制。实战选择标准如果你需要读取DOM几何属性比如元素宽高或者需要同步调整DOM位置避免闪烁用useLayoutEffect。其他情况包括发请求、设置定时器、订阅事件一律用useEffect。如果你误把大量计算放到useLayoutEffect里浏览器会被卡住用户感受到的就是页面操作极不流畅。我自己的原则是默认useEffect只有明确出现“闪烁”或者“布局抖动”问题时才升级成useLayoutEffect而且升级前必须先确认问题确实来自effect执行时机不要凭感觉乱换。5.4 并发特性里的useEffectstartTransition与useTransitionReact 18支持的并发特性对useEffect也有影响。尤其是使用startTransition的时候非紧急更新会被标记为低优先级React可以在更新时间片里暂停渲染此时useEffect的执行时机也会跟着进行调整。在真实业务中你通常不需要关心这种底层调度差异但如果你在做列表筛选、搜索联想这种高频更新把setState包进startTransition可以明显减少卡顿。一个实操建议搜索框打字时候输入框自身的value更新用紧急更新正常setState搜索结果的列表更新用startTransition包裹这样即使结果列表很大也不会阻塞用户继续打字。此时useEffect依然照常工作只是React会在有空的时候才执行effect你不需要在useEffect层做任何改动。6. 写在最后的几个小习惯写useEffect的这四年里我自己沉淀下来几条习惯算不上什么高深理论但对避免线上事故特别有用。第一每个useEffect只干一件事。如果一段逻辑里又要发请求又要绑定事件又要搞埋点拆成三个hook可读性直接上一个台阶。团队代码评审的时候单元效应比大杂烩好聊得多。第二所有异步逻辑里的setState都要加取消保护。哪怕你觉得“这个页面很简单不可能竞态”也别赌。人脑对异步顺序的判断能力极其有限加一个cancelled标记的成本几毛钱不加的代价可能是用户看到旧数据覆盖新数据然后截图来问你是怎么回事。第三依赖数组不是摆设也不是负担。每次你写useEffect我都建议默念一遍“这里依赖了哪些外部值如果这些值变了外部系统需要跟着变吗”想清楚再填数组比写完代码让ESLint告诉你缺依赖要靠谱得多。最后再分享一个我刚入行时踩过的坑。有次我做一个管理系统用户访问页面后要按角色权限渲染菜单我顺手把权限逻辑写进了useEffect然后里面又调用了setPermissions。那一次是典型的“在effect里派生state”依赖数组里放了userId和roleeffect里setPermissions而SetPermissions每次返回新对象导致又一个effect依赖了这个对象屏幕疯狂刷新。最后我把权限派生逻辑移到了渲染期的useMemo里整个链路瞬间清爽。这件事教给我的道理是useEffect虽然强大但它不是React世界的“万能刷新键”周公解梦似的让世界自动更新只会让代码进入无法预测的漩涡。真正稳妥的方式是认清哪些内容属于渲染哪些内容属于副作用然后把每一段逻辑放进它该待的位置。
延伸阅读

更多相关文章

2026/10/6 21:44:47

Simulink变压器故障仿真实战:从建模到波形判读

前几天有人问我,一台10kV配电变压器最近异响变大、顶层油温偏高,能不能靠Simulink做变压器故障仿真提前判断个八九不离十。这个问题放在十几年前,答案基本是停电、吊芯、做试验,周期长不说,有些隐性故障还不一定看得出…

2026/10/6 21:44:47

PFC电感磁芯选型三大核心参数与实战决策树

1. 为什么PFC电感磁芯选型不是“抄参数表”就能搞定的事?干电源设计这行十年,我见过太多工程师在PFC电感上栽跟头——不是温升爆表,就是效率掉点,要不就是EMI过不了。最典型的一幕是:项目快量产了,测试发现…

2026/10/6 21:44:47

WPF+helix-toolkit六轴机械臂3D可视化与正运动学控制实战

简介:这份源码资源面向具备一定WPF基础的.NET开发者与机器人方向学习者,聚焦如何用WPF控件编程结合Helix Toolkit实现六轴机械臂的三维可视化与关节控制,解决3D模型加载、旋转矩阵变换与实时交互等实践难点。压缩包共67个文件,约4…

2026/10/6 23:44:54

PHP登录安全实战:TOTP多因素认证、风控拦截与Redis会话一致性

前阵子接手一个老 PHP 电商项目,老板让我把登录安全做扎实。当时我对多因素认证、风控拦截、会话一致性这三块也只是有个大概认知,网上现成的库又不敢直接塞进生产环境,干脆从零开始写一套。正好手上有个 PHP 8.3 的空闲服务,配合…

2026/10/6 23:44:54

数组:算法竞赛的地基,从内存模型到高级数据结构的底层逻辑

很多同学刚接触算法竞赛时,第一反应是去啃各种“高大上”的算法——图论、动态规划、网络流、字符串匹配。但真正让我意识到“地基”重要性的,是一次比赛中因为数组开小导致半小时调不出错误、最后发现是边界问题的惨痛教训。数组,这个最基础…

2026/10/6 23:39:54

逆变器母线电容选型实战:耐压与纹波电流计算指南

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

2026/10/6 23:39:54

Zynq双千兆以太网硬件设计:RGMII时序收敛与PHY选型实战

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

2026/10/6 23:39:54

ST语言BYTE数组解析:Modbus字节序问题的本质与UDT解决方案

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

2026/10/6 23:39:54

DHCP协议原理与排错实战:从UDP端口67/68到状态机诊断

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

2026/10/5 6:32:56

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起:为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高,很多人第一次听到会以为是某个新模型的名字,其实它更像是一种思路——把Jev模型的能力当作底座,通过Agent的方式去接管浏览器&#xf…

2026/10/6 4:01:51

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同":多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西,大概率会有一种感觉:单个 Agent 能做的事情,其实很快就摸到天花板了。你给它一个提示词,挂几个工…

2026/10/6 17:46:51

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

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

2026/10/6 0:03:23

MR25H40CDF+STM32F031C6工业级高可靠数据存储方案

1. 项目概述:为什么在工业现场非得用 MR25H40CDF 配 STM32F031C6 做数据存储?在工厂产线的 PLC 控制柜里、在风电变流器的散热片背面、在矿井监测终端的金属外壳下,你经常能看到一块指甲盖大小的黑色芯片——它既不是 Flash,也不是…

2026/10/6 0:03:23

MRAM+STM32工业断电数据保全实战指南

1. 项目概述:为什么在工业现场非得用 MR25H40CDF 配 STM32F031C6 做数据存储?在工厂产线的PLC柜里、在野外无人值守的环境监测终端里、在高速运转的包装机控制板上,你经常能看到一块指甲盖大小的黑色芯片,旁边贴着“MR25H40CDF”丝…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑