【ArkUI 入门练中学】第19课:状态管理 V2 深度解析与迁移
本节目标· 理解状态管理 V2 的设计理念掌握其相比 V1 在深度观测与精准刷新上的核心改进· 掌握 ObservedV2 与 Trace 的配合机制能够实现对嵌套对象的自动深度观测· 掌握 V2 组件状态管理装饰器 Local、Param、Once、Event 的用法与 V1 对应关系· 掌握 Monitor 异步监听与 Computed 计算属性的使用理解 V2 监听能力相比 Watch 的增强· 了解 Provider / Consumer、SyncMonitor、Type、ReusableV2 等 V2 新增装饰器· 掌握 AppStorageV2 与 PersistenceV2 的使用方式理解其与 V1 存储方案的对应关系· 掌握从 V1 到 V2 的迁移策略与步骤理解 V1/V2 混用的限制条件· 能够为已有 V1 项目制定合理的 V2 渐进式迁移方案一、状态管理 V2 概述1.1 为什么需要 V2V1 的核心问题在于观测粒度。V1 使用代理来观测数据当创建状态变量时会同时创建一个数据代理观察者。这个机制在简单场景下工作良好但面对嵌套对象时存在根本性局限State 仅能观察对象的第一层属性变化深层嵌套的属性修改无法被感知。V1 通过 Observed ObjectLink 的组合解决了这个问题但代价是需要逐层创建自定义组件每一层都配上 ObjectLink代码复杂度随嵌套深度线性增长。当嵌套层级较深时代码会变得十分复杂易用性差。V2 对状态管理能力进行了全面升级实现了对数据对象的深度观察与管理能力。V2 通过 ObservedV2 和 Trace 装饰器支持对嵌套类对象属性的直接观测无需像 V1 那样依赖 ObjectLink 和自定义组件封装能够直接深度观测无需中间层。1.2 核心理念属性级精准刷新V2 的观测能力实现在类属性上而非组件层级上。V1 的 ObjectLink 观察的是“被 Observed 装饰的类实例”的属性变化而 V2 的 ObservedV2 Trace 将观测能力直接实现在类属性上——当类属性被 Trace 标记时无论嵌套多少层均能观测到变化。这意味着当被 Trace 装饰的属性变化时仅会通知该属性关联的组件进行刷新。这正是 V2 “属性级精准刷新”的核心——不是整个对象刷新不是整个组件刷新而是精确到使用了该属性的 UI 片段刷新。二、ObservedV2 与 Trace深度观测2.1 基本用法ObservedV2 是类装饰器用于状态管理 V2 中。ObservedV2 与 Trace 配套使用装饰类以及类中的属性使得被装饰的类和属性具有深度观测的能力。从 API version 12 开始支持。// 使用ObservedV2类装饰器使 Son 类具有深度观测能力ObservedV2classSon{// 使用Trace装饰器标记需要观测的属性属性变化时触发 UI 刷新Traceage:number100;}classFather{son:SonnewSon();}EntryComponentV2struct Index{father:FathernewFather();build(){Column(){Text(${this.father.son.age})// 设置点击事件点击后 age 值加 1由于Trace装饰器UI 会自动刷新.onClick((){this.father.son.age;})}}}注意Father 类没有被任何装饰器修饰但 Text 组件中使用了 this.father.son.age——当 age 变化时UI 依然会自动刷新。这是因为 Trace 将观测能力实现在了 Son.age 属性上与 Father 无关与组件层级也无关。2.2 嵌套类的观测规则在嵌套类中嵌套类中的属性被 Trace 装饰且嵌套类被 ObservedV2 装饰时才具有触发 UI 刷新的能力。如果嵌套层级中某一层不是 ObservedV2则该层的属性变化无法被追踪。ObservedV2classAddress{Tracecity:string北京;}// 必须也加ObservedV2否则 address.city 的变化无法被观测ObservedV2classUser{Tracename:string张三;address:AddressnewAddress();}关键规则如果 A 持有 BB 的字段要被观测B 本身必须是 ObservedV2 且字段加 Trace。只给外层加是不够的。路径上的每一层对象都需要是可观察的。2.3 与 V1 Observed / ObjectLink 的对比V1 的 Observed ObjectLink 方案要求嵌套对象逐层拆解自定义组件每一层配上 ObjectLink才能实现深度观测。V2 的 ObservedV2 Trace 则直接深度观测可删除中间层自定义组件代码量大幅减少且刷新粒度更细——属性级精准刷新而非组件级刷新。三、V2 组件状态管理装饰器3.1 ComponentV2ComponentV2 用于创建自定义组件是 V2 组件体系的入口。V1 的自定义组件中不可以使用 V2 的装饰器否则编译报错。当组件间不传递变量时V1 的自定义组件中可以使用 V2 的自定义组件。3.2 Local组件内部状态Local 对应 V1 的 State用于装饰组件内部的状态变量。关键差异· 简单类型可以直接将 State 替换为 Local。· 复杂类型V1 中的 State 可以观察复杂对象的第一层属性变化而 V2 中的 Local 只能观察对象自身的变化。如果需要追踪对象内部的属性变化必须结合 ObservedV2 和 Trace。· Local 禁止外部初始化V1 中 State 支持从外部传递初始值V2 中 Local 不允许。若需要从外部传递初始值使用 Param 和 Once。ComponentV2struct Counter{Localcount:number0;// 简单类型直接替换 Statebuild(){Button(计数${this.count}).onClick((){this.count;})}}3.3 Param组件外部输入Param 对应 V1 的 Prop用于接收父组件传递的数据。Param 是单向输入不建议在子组件中直接修改。ComponentV2struct Child{Paramval:number0;// 接收父组件传递的数据build(){Text(child:${this.val})}}3.4 Once初始化同步一次Once 用于 Param表示该参数只在初始化时从父组件同步一次之后父组件的更新不再同步到子组件。需要持续跟随父组件更新时不要给 Param 加 Once。3.5 Event规范组件输出Event 用于规范组件的输出事件通常与 Param 配合实现父子组件双向同步。在 V1 中 Link 允许父子组件之间双向数据绑定迁移到 V2 时可以用 Param 和 Event 模拟双向同步Param 实现父到子的单向传递子组件再通过 Event 回调函数触发父组件的状态更新。ComponentV2struct Child{Paramval:number0;EventaddOne:()void;// 通过回调通知父组件更新build(){Column(){Text(child:${this.val})Button(1).onClick((){this.addOne();// 通过 Event 回调通知父组件更新})}}}EntryComponentV2struct Parent{LocalmyVal:number0;build(){Column(){Text(parent:${this.myVal})Child({val:this.myVal,addOne:()this.myVal// Param 传递数据Event 传递回调})}}}3.6 双向绑定语法糖V2 提供了 !! 双向绑定语法糖用于简化 Param Event 的双向同步场景。其中 Event 方法名需要声明为 $ Param 属性名。// 子组件ComponentV2struct Child{Paramvalue:number0;Event$value:(val:number)void(){};build(){Button(${this.value}).onClick(()this.$value(this.value1))}}// 父组件中使用 !!Child({value:this.myVal!!})四、V2 新增能力Monitor 与 Computed4.1 Monitor状态变量修改异步监听Monitor 是 V2 的状态变量修改监听装饰器对应 V1 的 Watch但能力更强。关键增强Monitor 不仅能够感知变化后的数据还能获取变化前的数据。V1 的 Watch 只能感知变化后的值而 V2 的 Monitor 提供了 IMonitor 接口可以同时获取旧值和新值。ObservedV2classUserModel{Traceage:number0;Tracename:string;}ComponentV2struct DemoPage{Localuser:UserModelnewUserModel();Monitor(user.age)onAgeChange(monitor:IMonitor):void{// monitor.value() 返回本次变更的信息// 可以获取变化前的值和变化后的值console.info(age changed);}build(){Column(){Text(${this.user.age})Button(add).onClick((){this.user.age;})}}}Monitor 不触发的排查首先确认组件必须是 ComponentV2其次被监听的必须是状态变量、Trace 属性或 Computed最后 ObservedV2 实例要通过 new 创建且变化的字段必须加 Trace。路径监听Monitor 支持监听多个属性需要写清楚路径。监听深层对象时要写完整路径如 Monitor(‘user.address.city’)只写 city 只能监听当前作用域下名为 city 的状态。Monitor 是异步合并触发——一次事件里多个属性连续变化通常只回调一次拿到最终状态。如果需要每次赋值都同步触发使用 SyncMonitor。4.2 Computed计算属性Computed 是 V2 新增的计算属性装饰器。V1 无计算属性相关能力V2 可使用 Computed 避免重复计算。在 Computed 中计算的状态变量被改变时计算属性会重新计算。ObservedV2classPriceModel{Traceprice:number0;Tracecount:number1;Computedgettotal():number{returnthis.price*this.count;}}关键规则Computed 只有依赖的 Local、Param、Trace 等状态变化时才会触发 UI 重新计算和刷新。如果 price / count 没有 Trace打印 total 可能是新值但 UI 不一定会被标脏刷新。使用建议对于简单计算不建议使用计算属性因为计算属性本身也有开销。五、V2 全局状态管理5.1 AppStorageV2AppStorageV2 对应 V1 的 AppStorage是应用级内存状态管理方案。当数据变更时自动通知所有依赖组件更新。import{AppStorageV2}fromkit.ArkUI;ObservedV2exportclassPerson{Tracename:string;Traceage:number0;}// 创建或获取存储的数据constpersonAppStorageV2.connect(Person,key,()newPerson());5.2 PersistenceV2PersistenceV2 对应 V1 的 PersistentStorage是应用级数据持久化技术数据直接存在设备磁盘上退出重新进入后数据还存在。import{PersistenceV2}fromkit.ArkUI;// PersistenceV2 作为 AppStorageV2 的持久化引擎constconfigPersistenceV2.connect(AppConfig,config,()newAppConfig());注意V2 状态管理提供的是 AppStorageV2应用级内存状态和 PersistenceV2应用级持久化状态没有 LocalStorageV2。组件局部状态应使用 Local。六、V1 到 V2 迁移指南6.1 迁移策略对于新开发的应用建议直接采用 V2 版本进行开发。 对于已使用 V1 的应用如果 V1 的功能和性能满足需求无需立即切换至 V2。6.2 迁移步骤推荐的迁移节奏是先把组件装饰器换干净再处理数据类的 ObservedV2 化最后接 AppStorageV2、PersistenceV2 和 Repeat。整体门槛是 API 12。第一步组件装饰器替换将 Component 替换为 ComponentV2State 替换为 LocalProp 替换为 Param。注意 Local 禁止外部初始化Param 是只读的。第二步Link 场景处理V1 的 Link 双向绑定拆成 Param Event子组件发事件让父组件更新。或使用 Provider Consumer 实现跨层级双向同步。第三步数据模型 ObservedV2 化将 Observed 替换为 ObservedV2需要观测的属性加 Trace。嵌套类也要各自加 ObservedV2。第四步存储迁移AppStorage → AppStorageV2PersistentStorage → PersistenceV2。消费侧先迁只读页面再迁写入页面。6.3 V1/V2 混用限制V1 的自定义组件中不可以使用 V2 的装饰器否则编译报错。 当组件间不传递变量时V1 的自定义组件中可以使用 V2 的自定义组件。ObservedV2 和 Observed 嵌套使用时类对象能否被 V1 的装饰器装饰取决于最外层 class 使用的装饰器。如果最外层是 Observed 修饰的类可以和 V1 装饰器一起使用。渐进式迁移桥梁老 V1 组件可用 makeV1Observed 把 Observed 实例包装进 V2 体系做渐进式迁移不必一次性全改。七、多元化习题习题 1判断题题目在状态管理 V2 中Local 装饰的复杂对象可以观察其内部嵌套属性的变化无需额外装饰。答案错误解读V2 中的 Local 只能观察对象自身的变化即引用替换不能观察对象内部属性的变化。如果需要追踪对象内部的属性变化必须结合 ObservedV2 和 Trace。习题 2单选题题目以下哪个 V2 装饰器用于标记类属性为可观察使属性变化时触发关联 UI 刷新A. ObservedV2B. TraceC. MonitorD. Computed答案B解读ObservedV2 标记类为可观察Trace 标记类中的属性为可观察。只有被 Trace 装饰的属性变化才会触发 UI 刷新。Monitor 用于监听状态变量变化Computed 用于计算属性。习题 3多选题题目关于 V1 到 V2 的迁移以下说法正确的有多选A. State 在 V2 中对应 Local但 Local 禁止外部初始化B. Link 在 V2 中拆分为 Param EventC. Watch 在 V2 中对应 MonitorMonitor 能获取变化前的数据D. V1 的自定义组件中可以直接使用 V2 的装饰器答案A、B、C解读State 对应 LocalLocal 禁止外部初始化选项 A 正确。Link 拆分为 Param Event选项 B 正确。Watch 对应 MonitorMonitor 能获取变化前的数据选项 C 正确。V1 的自定义组件中不可以使用 V2 的装饰器否则编译报错选项 D 错误。习题 4代码填空题题目请补全以下代码使 User 类的 name 属性变化时能够触发 UI 刷新。______________classUser{______________ name:string张三;age:number25;}答案ObservedV2、Trace解读ObservedV2 装饰类使其具有深度观测能力Trace 装饰需要被观测的属性。只有被 Trace 装饰的属性变化才会触发 UI 刷新age 没有加 Trace其变化不会触发 UI 刷新。习题 5代码改错题题目以下代码存在错误请指出问题并修正。ComponentV2struct Child{Localcount:number0;// 从父组件接收数据build(){Text(${this.count})}}答案Local 禁止外部初始化不能用于接收父组件传递的数据。修正为使用 ParamComponentV2struct Child{Paramcount:number0;// 接收父组件传递的数据build(){Text(${this.count})}}解读Local 是组件内部状态禁止外部初始化。需要从外部传递初始值时应使用 Param。如果需要该参数只在初始化时同步一次可以配合 Once 使用。习题 6简答题题目简述 V2 的 ObservedV2 Trace 相比 V1 的 Observed ObjectLink 的核心优势。答案V1 的 Observed ObjectLink 方案要求嵌套对象逐层拆解自定义组件每一层配上 ObjectLink代码复杂度随嵌套深度线性增长。V2 的 ObservedV2 Trace 将观测能力实现在类属性上当类属性被 Trace 标记时无论嵌套多少层均能观测到变化。核心优势包括无需逐层创建自定义组件直接深度观测属性级精准刷新仅通知使用了该属性的 UI 片段刷新代码量大幅减少可删除中间层自定义组件。解读V2 的核心改进在于将观测能力从“组件层级”下沉到“类属性层级”。V1 需要组件层级配合才能实现深度观测V2 则直接在数据模型层面解决这正是 V2 被称为“能力升级”的根本原因。习题 7简答题题目简述 V1 到 V2 的迁移步骤以及 V1/V2 混用的核心限制。答案迁移步骤第一步将组件装饰器 Component 替换为 ComponentV2State 替换为 LocalProp 替换为 Param。第二步将 Link 双向绑定拆成 Param Event 或使用 Provider Consumer。第三步将 Observed 替换为 ObservedV2需要观测的属性加 Trace嵌套类也要各自加 ObservedV2。第四步将 AppStorage 迁移到 AppStorageV2PersistentStorage 迁移到 PersistenceV2。混用核心限制V1 的自定义组件中不可以使用 V2 的装饰器否则编译报错。当组件间不传递变量时V1 的自定义组件中可以使用 V2 的自定义组件。渐进式迁移可使用 makeV1Observed 将 Observed 实例包装进 V2 体系。解读迁移的核心原则是“逐步替换、渐进过渡”。V1 和 V2 可以在一个工程中共存但不能在一个组件内混用装饰器。迁移时应按组件逐个替换而非一次性全量改造。八、本节知识点总结V2 设计理念V2 将观测能力实现在类属性层级而非组件层级。ObservedV2 Trace 实现属性级精准刷新无需逐层创建自定义组件代码量大幅减少。核心装饰器映射Component → ComponentV2State → LocalProp → ParamLink → Param EventObserved ObjectLink → ObservedV2 TraceWatch → MonitorProvide / Consume → Provider / ConsumerAppStorage → AppStorageV2PersistentStorage → PersistenceV2。深度观测机制ObservedV2 标记类Trace 标记属性。嵌套类也需要各自加 ObservedV2 且字段加 Trace。只有被 Trace 装饰的属性变化才会触发 UI 刷新。V2 新增能力Monitor 支持获取变化前后的数据异步合并触发。Computed 提供计算属性能力避免重复计算。Once 控制 Param 只初始化同步一次。!! 语法糖简化双向绑定。存储方案AppStorageV2 应用级内存状态PersistenceV2 应用级持久化状态。V2 没有 LocalStorageV2组件局部状态使用 Local。迁移策略新项目直接采用 V2。已有 V1 项目逐步迁移建议按“组件装饰器 → 数据模型 ObservedV2 化 → 存储方案”的顺序进行。V1 组件中不能使用 V2 装饰器。下节预告第20课将进入 ArkUI 综合实战项目的学习从需求分析、架构设计到功能实现与性能优化完整走通一个 HarmonyOS 应用的开发全流程。

相关新闻

java线上cpu飙高排查实战详细步骤

java线上cpu飙高排查实战详细步骤

1.新建一个springboot项目 新加两个接口,一个是测试接口是否访问通过/test,另一个是专门模拟让cpu飙高的接口/loop,将其打包成一个jar放在服务器上。 package com.cao.controller;import org.springframework.web.bind.annotation.GetMapping…

2026/10/11 10:20:57 阅读更多 →
GitHub趋势周报:AI基础设施下沉与开发者工具崛起

GitHub趋势周报:AI基础设施下沉与开发者工具崛起

2026年第40周,GitHub Trending 上又换了一批面孔。我照例在周一早上把这一周的数据拉下来,逐项筛了一遍,发现这周的榜单有不少值得记录的变化:AI 项目的占比回落到三成以下,开发者工具、底层运行时这类项目开始挤进前排…

2026/10/10 9:03:43 阅读更多 →
Pytest实战指南:从fixture到参数化,打造高效自动化测试

Pytest实战指南:从fixture到参数化,打造高效自动化测试

1. 为什么是Pytest:它到底比unittest强在哪先聊个现实问题,很多人都问过我:Python自带的unittest不是也挺好的吗,为什么要换pytest?我在公司待过好几个项目,刚开始也是unittest一把梭。写一个测试用例&…

2026/10/11 10:32:29 阅读更多 →

最新新闻

识别虚假技术资源:Bishop深度学习2024真伪验证指南

识别虚假技术资源:Bishop深度学习2024真伪验证指南

简介:这是一本由机器学习权威Christopher M. Bishop与Hugh Bishop合著的深度学习前沿教材,面向高校研究生、AI研究人员及具备数学与编程基础的进阶学习者,系统构建从神经网络基础到Transformer、图神经网络等现代架构的理论框架。资源为单文件…

2026/10/11 10:57:28 阅读更多 →
如何将impeccable拆解为可执行的质量标准与检查清单

如何将impeccable拆解为可执行的质量标准与检查清单

1. 一个词撬动的思维革命:为什么"impeccable"值得深挖第一次看到"impeccable"这个词被单独拎出来当作项目标题,我的直觉是:这要么是个文字游戏,要么背后藏着某种极致追求。后来跟几个做产品和设计的朋友聊了一…

2026/10/11 10:57:28 阅读更多 →
CAPL脚本入门:掌握on start、on message与output三大核心函数

CAPL脚本入门:掌握on start、on message与output三大核心函数

1. 为什么第一个CAPL脚本值得认真对待很多人第一次接触CAPL,心态都是“先跑起来再说”。这个思路没错,但问题在于,如果第一个脚本只是照抄示例、点下编译、看到没有报错就结束,那基本等于没入门。后面一旦遇到真实项目里的报文周期…

2026/10/11 10:57:28 阅读更多 →
操作系统实验报告写作指南:进程调度、内存管理与并发同步实战

操作系统实验报告写作指南:进程调度、内存管理与并发同步实战

简介:这份资源是西安电子科技大学操作系统课程的上机实验报告,面向正在学习操作系统、需要完成进程与线程相关实验的高校学生及自学者。报告围绕Linux环境下C语言编程展开,完整覆盖进程建立、线程共享进程数据、信号通信、匿名管道与命名管道…

2026/10/11 10:57:28 阅读更多 →
无DOM测试与happy-dom:bloub如何验证导出缺陷的测试体系

无DOM测试与happy-dom:bloub如何验证导出缺陷的测试体系

前端图形学 【免费下载链接】bloub SVG recreation of the x.ai bot avatar. One shape morphing through 14 states, measured off the reference video frame by frame. 项目地址: https://gitcode.com/gh_mirrors/bl/bloub 点击查看 免费下载 bloub 是一个用 SV…

2026/10/11 10:57:28 阅读更多 →
小学组C++算法赛初赛备考指南:从真题拆解到避坑技巧

小学组C++算法赛初赛备考指南:从真题拆解到避坑技巧

简介:这份资源是2024年信息素养大赛C算法创意实践挑战赛小学组初赛的真题解析文档,面向小学阶段对编程有兴趣、已具备一定C基础的学习者,也适合指导教师作为教学参考。内容覆盖单选题与判断题两种题型,涉及变量定义、运算符、布尔…

2026/10/11 10:56:27 阅读更多 →

日新闻

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

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

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

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

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

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

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

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

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

2026/10/11 0:00:27 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 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/11 10:45:37 阅读更多 →
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/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练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/10 10:38:42 阅读更多 →