Vue3 按钮互斥显示:状态设计、v-if/v-show 与组合式API
做后台管理系统的时候我遇到过一个特别常见、又特别容易被写歪的需求页面上放两个按钮一个叫“启动”一个叫“关闭”同一时刻只能显示其中一个。启动的时候你看不到关闭关闭之后你看不到启动这就是典型的 Vue3 按钮互斥显示场景。这个需求看起来简单到不能再简单但我在评审新人代码和逛技术社区时见过好几种写法有人用两个布尔变量在事件里互相置位有人在模板里复制粘贴了一大段 v-if/v-else还有人把按钮的显示条件写在事件回调里。这篇我就从 Vue3 组合式 API 的角度把这个“启动 / 关闭互斥显示”场景从头拆一遍覆盖状态设计、v-if/v-show 选型、可访问性、异步竞态这几个真实会踩的坑最后给一个能直接抄的 composable 封装。适合刚接手 Vue3 项目的开发者也适合想把按钮交互写得更稳的人参考。1. 互斥切换场景的本质状态只有一份视图只是状态的投影先看本质。互斥显示的难点不在“怎么让一个按钮隐藏”而在于“两个按钮背后的业务状态到底是什么”。启动 / 关闭说白了就是一个设备、一台任务当前是否在运行。页面上显示“启动”还是“关闭”只是这个运行状态在不同取值下的两种投影。1.1 双布尔变量的反模式为什么手动互置必出问题最容易被新人写出来的版本是这样的script setup import { ref } from vue // 反模式两个布尔变量手动互相置位 const showStart ref(true) const showStop ref(false) function handleStart() { showStart.value false showStop.value true } function handleStop() { showStop.value false showStart.value true } /script这段代码在只有两个按钮、事件链路简单的 demo 里确实能跑通但敌人不是现在而是你往里面加东西的时候。我手里有过一个真实改动要在启动成功后把按钮临时变成“启动中”禁止点击三秒。如果用双变量方案你得同时维护showStart、showStop、isStarting三个状态任何一个赋值顺序错了页面就会出现两个按钮同时显示或者全部消失的诡异画面。更麻烦的是双变量之间没有任何强约束。A 同学今天临时在handleStart里加了一句showStart.value true明天按钮就永远停留在启动态排查起来要沿着所有赋值语句一个个看。同行评审时看到这种代码第一反应基本都是一句“这里为什么不用一个布尔值”。我习惯用一个生活类比来解释这个问题房间里的灯不会有两个开关状态一个开着另一个关着灯只有一个真实的亮 / 灭状态进门处的那个开关只是这个状态的控制器。按钮显示同理。你只需要一个isRunning不需要两个互相看脸色的变量。1.2 单一布尔值 派生显示Vue3 组合式 API 的最小实现正确的做法是让“运行状态”成为唯一事实来源按钮的显示与否由它派生script setup import { ref } from vue const isRunning ref(false) function handleStart() { isRunning.value true } function handleStop() { isRunning.value false } /script template div classdevice-actions button v-if!isRunning clickhandleStart启动/button button v-else clickhandleStop关闭/button /div /template这里模板里的!isRunning就是派生条件。按钮一上一下永远只有一个进 DOM因为isRunning在任何一个时刻都只能是真或假——它在逻辑上就是互斥的。如果判断条件复杂比如“设备在线且未运行且权限通过”才能显示启动按钮我建议把派生条件抽出来变成computed。一方面模板干净另一方面computed会被缓存不会在每次渲染时重新计算script setup import { ref, computed } from vue const isRunning ref(false) const canStart computed( () deviceOnline.value !isRunning.value hasPermission.value ) /script至于状态容器用ref还是reactive这个场景我倾向于用ref。启动 / 关闭只有一个布尔值ref写起来最直接赋值的语义也清楚。如果以后要存设备对象、历史记录这类聚合数据再考虑reactive。类型上还可以用 TypeScript 把isRunning声明成Refboolean不过日常开发里正常推导就够了。2. v-if 与 v-show 的选择性能、状态保留与交互语义讲完状态设计接着看模板里的两个渲染方案。互斥显示最常用的是v-if/v-else但也有人习惯用v-show。这两个指令看着都能让按钮“消失”实际行为和适用场景差不少。2.1 一张表看透 v-if 和 v-show 的差异下面这张表是我在内部培训时最喜欢用的对照维度v-ifv-show条件为假时的 DOM元素直接从 DOM 树移除不渲染元素始终渲染只是加display:none初始渲染开销条件为假时几乎为零省掉 DOM 创建无论真假都渲染首屏有额外开销切换开销需要销毁和重建 DOM组件内状态全部丢失只切换一个 CSS 属性开销极小内部状态不保留每次重建都是全新的保留包括输入框内容、滚动位置、定时器适用场景低频切换、节点数量多、条件在初始就确定高频切换、需要保留子组件状态最容易误导人的是“v-show 性能好”这个说法。v-show 的切换确实便宜但它把“不显示”的节点也一直留在 DOM 里。如果这个按钮里面有复杂的子组件v-show 会让它在页面整个生命周期里白白挂载。反过来如果两个按钮切换频率极低根本没人连续狂点“启动”和“关闭”v-if 重建 DOM 的开销完全可以忽略不计。2.2 按钮互斥场景的选型建议和 v-if/v-else 的硬约束回到“启动 / 关闭互斥显示”这个具体场景我的建议是如果两个按钮是低频切换比如用户点一下“启动”之后运行几十分钟甚至几天默认用v-if。按钮是轻量节点销毁重建成本可以忽略而且不显示的按钮不在 DOM 里更干净。如果状态会高频变化比如页面轮询设备状态每秒可能要切好几次显示这时用v-show更稳避免频繁创建和销毁引起的布局抖动。如果按钮内部有输入框、表单校验这类需要保留状态的组件v-show再合适不过。但按钮互斥场景里按钮一般没有内部状态v-if足够。还有一个v-if/v-else的硬约束容易踩v-if和v-else之间不能插入其他节点。中间哪怕写了一个注释节点Vue 也会警告v-else找不到匹配的v-if。我在真实项目里见过有人为了排版在两个按钮之间加了一个span结果“关闭”按钮直接消失控制台报了一堆警告。要留空隙就用 CSS 的 margin 或者 flex 的 gap不要在两者中间塞元素。3. 从互斥到可访问性隐藏、禁用与焦点管理的三个细节很多前端做到“按钮能切换”就收工了但实际用户里有一类靠键盘操作的人还有一类用屏幕阅读器的人。这两个群体会遇到一些鼠标用户完全无感的问题。3.1 隐藏、禁用和 aria-disabled三种交互语义的取舍先想清楚一个问题启动 / 关闭场景里未激活的那个按钮到底应该“消失”还是“禁用”很多人不加区分其实要看业务语义。当前操作不适用用户不需要看到它用v-if隐藏。例如设备已经运行中启动按钮就完全没有存在意义。操作可见但当前不允许点击用disabled。例如服务正在重启启动和关闭都可见但都禁用了。操作可见需要读屏软件明确告知“不可用”用aria-disabledtrue。它保留了点击能力用来做自定义交互或展示 tooltip 时比较灵活。我给一个区分表交互语义推荐方式说明操作不适用不应暴露v-if / v-show按钮从可访问性树中移除操作可见但暂不可用disabled同时阻止点击事件和 Tab 聚焦操作可见且想保留点击aria-disabledtrue需要自己拦截事件并配合读屏文案按钮互斥显示这个标题下最自然的是第一种状态切到“运行中”启动按钮从可访问性树里消失读屏用户听到的只有“关闭按钮”。这比那种“两个按钮都显示但一个 disabled 变灰”的做法在语义上更接近真实设备面板。3.2 按钮被 v-if 移除后键盘焦点去哪里了这一节是我在无障碍审查时经常发现的真实问题。用键盘 Tab 键操作页面时焦点如果恰好停在“启动”按钮上用户按下回车触发handleStartv-if立刻把“启动”按钮从 DOM 中移除。此时焦点的宿主元素消失了浏览器会把焦点丢回 body。下一次用户按 Tab焦点会从页面顶部重新开始而不是进到新出现的“关闭”按钮上。对键鼠并用的人这只是一个跳转对手柄键盘用户和读屏用户来说整个操作流就断了。修复思路是切换状态后主动把焦点交给新的按钮。用nextTick等待 DOM 真正更新再调用focus()script setup import { ref, nextTick } from vue const isRunning ref(false) const stopButtonRef ref(null) async function handleStart() { isRunning.value true await nextTick() stopButtonRef.value?.focus() } /script template div classdevice-actions button v-if!isRunning clickhandleStart启动/button button v-else refstopButtonRef clickhandleStop 关闭 /button /div /template这里有个容易翻车的细节ref 关联的元素是 v-else 分支里的按钮在isRunning还是false时这个 ref 是null所以要放在handleStart里、等状态翻转并且 DOM 更新之后再访问。我之前见过有人把this.$refs写在状态更新前结果拿到的永远是 null。加一个可选链?.避免报错再配合await nextTick()这个问题就解决了。如果不想强行抢焦点另一个折中做法是让“关闭”按钮保持在 Tab 顺序中但对于状态切换类操作主动把焦点递交给下一步要操作的按钮体验上更接近原生应用的交互习惯。4. 我在生产环境踩过的坑异步竞态导致切换状态回弹状态、渲染方案、可访问性都讲完了接下来聊一个我在某个设备管理后台真实踩过、而且排查了很久的坑。现象描述起来很轻描淡写“点关闭按钮按钮闪了一下又变回启动。”但根因牵扯到异步竞态值得完整复盘一遍排查思路。4.1 现象复现按钮闪了一下又立即变回去那个后台页面的逻辑是点击“关闭”后前端乐观更新先把isRunning置为 false让界面立即切到“启动”按钮同时向后端发一个关闭设备的请求。页面还有一个定时器每 5 秒轮询一次设备实时状态把结果同步到页面上。现象是点击“关闭”后“启动”按钮出现了大约一两秒然后又被“关闭”按钮顶回去。第一次遇到时我以为是接口返回了 running 状态导致轮询又把isRunning赋成 true。但我查了后端日志设备明明已经停了接口也返回了停。那问题一定出在前端。4.2 排查链路从事件、watch 到竞态根因我当时的排查分四步。第一步确认事件有没有触发。在handleStop里打日志确认点击确实进了函数isRunning也确实被置成 false。第二步给isRunning加watch打印每次变化的前后值和调用栈。这一步是关键watch 日志显示isRunning先变成 false约 300ms 后又变成 true而且变成 true 时的调用栈不在 handleStop 里而是来自轮询回调。第三步把轮询回来的 deviceState 打出来发现确实是stopped。那为什么stopped会被翻译成isRunning true我翻开轮询处理代码看到这样一个判断if (deviceState running || deviceState starting) { isRunning.value true } else { isRunning.value false }初看没问题stopped会走到 else 置 false。但问题在于轮询函数还另外维护了一个“上一次状态”的临时变量用来判断状态是否发生变化。那个临时变量在点击“关闭”之前仍然保存着旧值 running轮询回来后又用旧值做了一次增量判断不小心把isRunning又赋回了 true。这就是典型的异步竞态两个异步链路都在修改同一个状态谁后到谁覆盖。第四步复现验证。我把轮询暂停手动点击“关闭”按钮正常切换恢复轮询问题复现。确认根因后我给状态变更加了一个请求序号裁决机制。4.3 修复思路乐观更新 最新请求裁决核心思路是每次发起操作时生成一个递增的请求 ID只有“最新一次操作”的回调才有资格写回状态。旧请求即便晚到也直接丢弃。这样无论轮询还是手动操作都不会出现旧数据覆盖新状态的问题。import { ref } from vue const isRunning ref(false) let latestRequestId 0 async function handleStop() { const currentId latestRequestId // 乐观更新让 UI 先给出反馈 isRunning.value false try { const ok await stopDevice() // 接口成功返回 true // 旧请求没有写回资格直接丢弃 if (currentId ! latestRequestId) return // 以接口结果为准成功保持关闭失败回滚为运行中 isRunning.value ok ? false : true } catch (error) { // 失败回滚也要先确认自己是最后一个请求 if (currentId latestRequestId) { isRunning.value true } } }另外轮询同步那里也要加同样的判断只有用户没有正在执行手动操作时轮询结果才有资格更新状态。更干净的做法是把“手动操作中”定义成一个isSyncing标志轮询期间遇到isSyncing就直接跳过同步。这里我要多说一句很多“按钮切换失效”的 bug根子都在状态被多处写。一个状态最好只有一个写入源头其他位置只能读。Vue 不像 Redux 那样强制单向数据流所以团队里尤其要靠约定和代码评审来守住这条线。4.4 延伸坑组件卸载后的状态更新与连点请求同类竞态还有一个变体请求还没回来组件已经被销毁了。比如用户从设备管理页跳到其他路由结果关闭设备的请求回调里还写isRunning.value控制台会刷一些组件卸载相关的警告严重时甚至内存泄漏。修复很简单在onBeforeUnmount里置一个卸载标志回调里遇到标志就直接 return。import { ref, onBeforeUnmount } from vue const isRunning ref(false) let isUnmounted false onBeforeUnmount(() { isUnmounted true }) async function handleStop() { isRunning.value false try { await stopDevice() if (isUnmounted) return // 正常更新 } catch (e) { if (isUnmounted) return isRunning.value true } }还有连点问题。如果关闭按钮点击后没有立刻隐藏而是进入 loading 态用户连点两次就会发出两个关闭请求。我习惯在handleStop入口处加一个isSubmitting判断请求期间直接 return。这样配合上面说的请求 ID双保险。5. 从双按钮到多状态互斥配置表驱动与组合式封装文章最后一部分我聊聊扩展。真实业务里“启动 / 关闭”往往是第一步后面大概率会演化成“启动、暂停、恢复、结束”四种状态或者更复杂的“空闲、运行中、已暂停、异常、已结束”五种状态。这时候再写一堆 v-if/v-else 就不是不行而是维护成本会失控。5.1 布尔值不够了用字符串联合类型表达状态四个按钮的互斥核心状态不再是布尔值而是一个枚举语义的字符串。用 TypeScript 的联合类型可以把合法取值锁死type MachineState idle | running | paused | stopped const state refMachineState(idle)这样isRunning、isPaused这些派生判断用computed就能算。但按钮越来越多时我更推荐直接维护一张“状态 - 可执行动作”的配置表。5.2 配置表驱动渲染加状态只改一行数据import { ref, computed } from vue type MachineState idle | running | paused | stopped interface ActionItem { label: string next: MachineState } const state refMachineState(idle) const actions computedActionItem[](() { const actionMap: RecordMachineState, ActionItem[] { idle: [{ label: 启动, next: running }], running: [ { label: 暂停, next: paused }, { label: 结束, next: stopped }, ], paused: [ { label: 恢复, next: running }, { label: 结束, next: stopped }, ], stopped: [], } return actionMap[state.value] }) function dispatch(next: MachineState) { state.value next }模板里不再写任何 if/else直接遍历配置template div classmachine-actions button v-foraction in actions :keyaction.next clickdispatch(action.next) {{ action.label }} /button /div /template新增一个“启动中”状态只需要在MachineState和actionMap里加一项模板完全不用动。这一点在多人协作时价值极高因为模板的改动往往比纯数据的改动更容易引起冲突。5.3 把互斥逻辑装进 composable团队可复用的封装如果多个页面都要用这种互斥按钮把逻辑抽成 composable 是最好的选择。复用起来比复制粘贴一堆状态和方法要安全得多// useMachineState.ts import { ref, computed } from vue export interface ActionItemT extends string { label: string next: T } export function useMachineStateT extends string( initial: T, transitions: RecordT, ActionItemT[] ) { const state refT(initial) const actions computed(() transitions[state.value]) function dispatch(next: T) { state.value next } return { state, actions, dispatch } }页面里用起来很干净const { state, actions, dispatch } useMachineState(idle, { idle: [{ label: 启动, next: running }], running: [{ label: 关闭, next: stopped }], stopped: [{ label: 重启, next: running }], })模板template div classdevice-actions button v-foraction in actions :keyaction.next clickdispatch(action.next) {{ action.label }} /button /div /template这里有一个 Vue3 模板解包的细节容易踩如果直接把 composable 返回值整体挂在 setup 返回里模板中写machine.actions拿到的是一个 Ref 对象而不是数组因为嵌套在普通对象里的 ref 不会自动解包。所以在组件里使用 composable 时一般先把state、actions、dispatch解构到顶层再 return 出去让模板拿到的actions是解包后的数组。如果你想用machine.xxx这种写法可以用reactive包一层返回值但解构到顶层是更常见、也更直观的姿态。5.4 配置表方案的小坑与收尾经验配置表驱动也有自己的坑最常见的是 key 的选择。初版我写过:keyaction.label后来产品把“关闭”改成“停止”单纯文案变化倒没事但一旦两个状态的按钮文案互换Vue 会认为是同一个元素触发不了应有的重建。我给的建议是用action.next也就是目标状态做 key。目标状态在配置表里是唯一且稳定的文案怎么改都不影响节点身份。回到标题的“启动 / 关闭互斥显示”场景。如果你想在自己项目里快速落地其实有两个层次两个人写的小页面直接用一个布尔值加 v-if/v-else 就够了简单直接团队项目或未来要扩展状态建议从一开始就用配置表驱动加 composable。我个人做过十几个类似的后台页面后的体会是底部按钮区往往是最容易被低估的地方但它恰恰是用户和系统状态打交道最频繁的入口。把唯一状态源、渲染方案和竞态处理这三件事想清楚比记住任何一个框架 API 都重要。最后再分享一个习惯任何按钮切换的逻辑我都会在代码评审时问一句“这个状态还有没有其他写入方”每次这么问都能钓出不少隐患。

相关新闻

ClickHouse配置持久化全解:文件结构、热加载与排坑实战

ClickHouse配置持久化全解:文件结构、热加载与排坑实战

接手 ClickHouse 实例 ck-ec818311 的时候,我第一件事就是把它的配置持久化逻辑彻底捋了一遍。原因很简单——这是个分析型集群里的关键节点,配置一旦在重启后丢失,整个查询链路都会受影响。配置持久化,说白了就是让 ClickHouse 的…

2026/10/13 18:51:53 阅读更多 →
YOLOv3行人检测实战:VOC2012数据抽取、锚框聚类与训练调优

YOLOv3行人检测实战:VOC2012数据抽取、锚框聚类与训练调优

1. 项目缘起与整体设计思路行人检测这个方向,我在实际项目里接触过不少次,从最早的 HOGSVM 一路做到现在的深度学习方案,踩过的坑可以说能写满一个笔记本。这次要聊的是用 YOLOv3 来训练一个专门的行人检测模型,数据来源是从 VOC2…

2026/10/13 18:51:53 阅读更多 →
ClickHouse配置持久化:从SET到ALTER USER,解决重启丢配置

ClickHouse配置持久化:从SET到ALTER USER,解决重启丢配置

相信不少同学在做ClickHouse交付或者日常运维时,都有过这么一段糟心经历:业务侧报了一个慢查询,你连上实例,改了max_threads、调了max_memory_usage,SQL直接跑起来了,你以为完事大吉。结果第二天一上班&…

2026/10/13 18:51:53 阅读更多 →

最新新闻

Cursor额度重置教程:设备指纹清理实现合规续杯

Cursor额度重置教程:设备指纹清理实现合规续杯

简介:本资源是面向软件开发者的 Cursor 编辑器 11 月续杯实战源码包,聚焦解决免费用户模型调用受限、账号续期繁琐等实际痛点,适用于中初级开发者快速提升 AI 编程效率。压缩包共 3 个文件,含 .inscode(Cursor 插件配置…

2026/10/13 19:38:20 阅读更多 →
用Claude Code摸清老项目技术栈:三轮提示词框架与实战记录

用Claude Code摸清老项目技术栈:三轮提示词框架与实战记录

“只管去写”系列到了第二天。今天的任务很明确:用Claude分析一个老项目的技术栈。这件事听起来远没有写一个新功能那么有成就感,但只要你接过大半年之前自己写的代码、接过离职同事留下的半成品项目、或者刚入职需要快速搞清一套业务系统的底细&#xf…

2026/10/13 19:38:20 阅读更多 →
开源协作的隐形基石:高效代码评审实践指南

开源协作的隐形基石:高效代码评审实践指南

做开源项目这几年,我越来越确信一件事:代码评审(code review)是整个协作链条里最被低估的一环。很多人觉得代码写完、测试跑通、合并进去就完事了,可真正把一个项目推过几个版本之后才发现,评审才是让代码质…

2026/10/13 19:38:20 阅读更多 →
Python pickle序列化实战:从协议版本到安全红线全解析

Python pickle序列化实战:从协议版本到安全红线全解析

如果你写过 Python,一定遇到过这类需求:程序跑完把内存里的字典、列表或者某个自定义类实例保存到磁盘,下次启动再原封不动读回来。Python 为此内置了一个序列化模块叫 pickle,标题说得很直白——Pickle 是 Python 内置的序列化模…

2026/10/13 19:38:20 阅读更多 →
AnyPS5:不越狱的PS5增强方案与边界协同架构

AnyPS5:不越狱的PS5增强方案与边界协同架构

项目标题:“AnyPS5”这个名称本身带有强烈的指向性与模糊性并存的特征——它既像一个技术代号,又像一句口号;既暗示兼容性、泛用性(“Any”),又锚定在特定硬件生态(“PS5”)。但问题…

2026/10/13 19:38:20 阅读更多 →
互联网大厂薪酬结构全解析:总包、级别、绩效与谈薪技巧

互联网大厂薪酬结构全解析:总包、级别、绩效与谈薪技巧

1. 先说结论:今年这个薪酬盘子到底什么情况每年这个节点,总有人拿着某头部互联网平台的薪酬截图或者 Offer 在各个群里问“这个数正常吗”。说实话,我在这一行摸爬滚打了十几年,带过团队、做过招聘、也背过绩效,今年这…

2026/10/13 19:37:19 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/12 18:11:17 阅读更多 →