首页/新闻资讯/正文详情

Formily Reactive 的 raw API 详解:如何从 observable 对象中取回源数据

发布时间:2026/9/23 13:43:34 来源:云帆数科 栏目:资讯中心
Formily Reactive 的 raw API 详解:如何从 observable 对象中取回源数据
前端UI组件【免费下载链接】formily Cross Device High Performance Normal Form/Dynamic(JSON Schema) Form/Form Builder -- Support React/React Native/Vue 2/Vue 3项目地址https://gitcode.com/gh_mirrors/fo/formily点击查看免费下载导读raw是formily/reactive响应式核心中一个用于「取回源数据」的底层工具函数。在 Formily 的响应式体系中observable创建的对象是一个 Proxy 代理日常读写都应经由代理完成以保证依赖收集与响应式更新raw则提供了一条绕过代理、直接拿到原始对象的通道。本文基于 raw API 文档中文版见 raw.zh-CN.md结合 formily/reactive 包的源码实现与测试用例详细讲解该 API 的签名、行为边界、内部实现原理以及与toJS、markRaw等关联 API 的异同帮助你在确有需要时安全、正确地使用它。基本描述从 observable 中获取源数据raw的作用非常单一从 observable 对象中获取其源数据原始对象。在 Formily 的响应式架构中observable()会把传入的普通对象包装为 Proxy相关实现见 internals.ts 中的createNormalProxy/createCollectionProxy。此后我们对这个对象的所有读写都会被拦截从而触发依赖收集与副作用通知。而raw返回的正是这个 Proxy 背后未被包装的原始对象。文档同时给出了一个重要提醒这也是本 API 的第一条使用边界注意只能获取当前对象的源数据不包括深层对象属性。即raw(obs)只能拿到obs这一层对应的源对象如果obs的某个属性值是嵌套的 observable 代理如示例中的obs.aa需要单独对obs.aa调用raw才能拿到那一层嵌套对象的源数据。函数签名文档中给出的类型签名如下interface rawT extends object { (target: T): T }入参任意对象target通常是observable()创建的代理对象返回值类型与入参相同实际返回对应的源对象泛型约束为object因为observable体系只针对对象含数组、Map、Set 等集合类型生效。从类型签名可以看出raw是类型安全的传入代理得到的是其源对象类型编译期即可保持一致。基础用例文档给出了最直接的使用示例import { raw, observable } from formily/reactive const obs observable({}) obs.aa { bb: 123 } console.log(raw(obs)) // 输出源对象原始对象 console.log(raw(obs.aa)) // 输出嵌套对象 aa 的源对象这里有两层含义需要展开obs.aa { bb: 123 }这行赋值发生在代理上。由于observable默认是深响应式的obs.aa本身也会被包装为 observable 代理见 internals.ts 中createObservable对嵌套值的递归处理。raw(obs)拿到的是一层源对象raw(obs.aa)拿到的是嵌套对象aa这一层的源对象。两者互不包含——这正是文档中「不包括深层对象属性」的实际体现。源码实现raw 到底做了什么raw的实际实现位于 externals.tsexport const raw T(target: T): T { if (target?.[ObModelSymbol]) return target[ObModelSymbol] return ProxyRaw.get(target as any) || target }该实现依赖 environment.ts 中维护的两个全局映射ProxyRaw: WeakMap记录「代理对象 → 源对象」的映射ObModelSymbolSymbol(ObModelSymbol)用于模型modelAPI场景下标记源对象。因此raw的取值逻辑分为两条路径如果target是model()创建的模型对象带有ObModelSymbol则直接返回target[ObModelSymbol]记录的源对象否则从ProxyRaw这个 WeakMap 中查询代理对应的源对象如果查询不到说明传入的本身就不是 observable 代理则原样返回入参。这意味着raw是一个「安全降级」的函数对任意非代理对象调用raw得到的就是它自己不会报错。这一点非常实用例如在不确定一个值是否被observable包装过时可以直接调用raw而不必先做判断。同时由于ProxyRaw是 WeakMap键为对象弱引用raw的查询不会造成内存泄漏也无需手动清理映射关系。代理创建的对应关系要理解raw为什么有效需要看代理创建时两个映射是如何成对写入的internals.tsconst createNormalProxy (target: any, shallow?: boolean) { const proxy new Proxy(target, baseHandlers) ProxyRaw.set(proxy, target) // 代理 - 源对象 if (shallow) { RawShallowProxy.set(target, proxy) } else { RawProxy.set(target, proxy) } return proxy }ProxyRaw保存「代理 → 源对象」供raw反查RawProxy/RawShallowProxy保存「源对象 → 代理」供内部判断一个源对象是否已有对应代理避免重复包装。两者互为反向索引raw就是利用了其中的ProxyRaw方向。行为边界与注意事项1. 只取当前层不取深层再次强调文档中的核心警告raw只返回当前对象的源数据嵌套的深层对象属性不会被一并还原。若需要递归地把整个对象树还原为纯 JS 数据应使用toJS同为 externals.ts 中导出的 API它会对可观察对象进行递归深拷贝式还原并内置WeakSet防止循环引用导致的死循环。2. 拿到的源对象不再具备响应式能力通过raw拿到的源对象是原始引用直接对它进行读写不会触发任何依赖收集或响应式更新。因此在业务代码中用raw取到的数据只能用于「只读查看」或「一次性导出」等场景不应作为持续读写的数据源。3. 为什么不推荐使用文档明确指出「通常情况下并不推荐使用该 API」。原因在于响应式体系的正确用法是始终经由代理访问数据这样autorun、reaction、observer等才能正确收集依赖。一旦通过raw绕过代理访问很容易破坏依赖收集的完整性造成视图不更新或逻辑时序错乱的隐性 bug。绝大多数「需要原始数据」的场景都可以改用toJS完成。4. 集合类型同样适用raw对Map、Set、WeakMap、WeakSet等集合类型的 observable 代理同样生效createCollectionProxy同样会写入ProxyRaw见 internals.ts。在 collections-map.spec.ts 等测试中可以看到expect(raw(map)).toBeInstanceOf(Map) expect(raw(set)).toBeInstanceOf(Set) expect(raw(weakMap)).toBeInstanceOf(WeakMap) expect(raw(weakSet)).toBeInstanceOf(WeakSet)5. 与 markRaw 的关系raw取回源数据与markRaw标记对象为不可响应是两条互补的边界工具markRaw用于在observable包装时跳过某些对象externals.ts其实现是给目标对象打上RAW_TYPE标记isSupportObservable在判断「对象是否可被包装」时会优先检查RAW_TYPE标记并直接返回falseexternals.ts从而保证被markRaw标记过的对象永远不会成为代理。也就是说markRaw阻止对象被代理raw则是把已被代理的对象还原。两者都服务于「在某些场景下需要访问原始对象」的需求但入口与语义不同。测试用例佐证raw的行为在 packages/reactive/src/tests目录下有充分覆盖除上述集合类型断言外还有大量用例通过raw直接操作源对象来验证响应式行为在 collections-set.spec.ts 中raw(set).add(value)、raw(set).delete(value)、raw(set).clear()直接作用于源 Set在 collections-map.spec.ts 中raw(map).set(key, Hello)、raw(map).delete(key)、raw(map).clear()同理在 collections-weakmap.spec.ts 与 collections-weakset.spec.ts 中也通过raw对 Weak 集合执行增删操作。这些用例一方面验证了raw返回的确实是可直接操作的原生集合实例另一方面也演示了raw的典型测试用法——在测试中绕过代理直接操控源对象以便精确构造或断言底层状态。总结与建议要点说明作用从 observable 代理对象中取回源数据签名rawT extends object(target: T): T返回规则代理 → 源对象模型对象 →ObModelSymbol记录值非代理 → 原样返回深层限制只取当前层源数据不递归还原深层属性推荐替代需要递归还原纯数据时使用toJS使用禁忌拿到的源对象不具备响应式能力不应作为常规读写数据源raw是formily/reactive中一个「存在但默认不应使用」的低层 API。理解它的实现ProxyRaw反查与边界仅当前层、非响应式有助于你深入理解 Formily 响应式体系中「代理 / 源对象」的双层结构而在实际业务中请优先遵循官方建议用toJS或直接经由代理访问数据仅在测试、调试或确需绕过代理的极少数场景下才使用raw。赞分享前端UI组件【免费下载链接】formily Cross Device High Performance Normal Form/Dynamic(JSON Schema) Form/Form Builder -- Support React/React Native/Vue 2/Vue 3项目地址https://gitcode.com/gh_mirrors/fo/formily点击查看免费下载相关推荐formily/reactive hasCollected 详解如何检测依赖是否被收集formily/reactive hasCollected 详解如何检测依赖是否被收集 hasCollected 是 formily/reactive 响前端UI组件Clarity热力图生成指南深度解析用户点击和滚动行为模式Clarity热力图生成指南深度解析用户点击和滚动行为模式 Clarity是一款强大的行为分析库它通过监控DOM变化和用户交互来生成聚合洞察帮助开发者深入人工智能语音音频AI 应用OpenBMBFormily Reactive 的 markObservable强制接管对象的响应式劫持机制Formily Reactive 的 markObservable强制接管对象的响应式劫持机制 导读 markObservable 是 formily/re前端UI组件创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

Python电影推荐系统:基于协同过滤算法的设计与实现
Python电影推荐系统:基于协同过滤算法的设计与实现

简介:基于协同过滤推荐算法的电影推荐系统完整毕业设计项目,适合计算机、通信、人工智能、自动化等专业学生用于毕业设计或课程设计学习。项目采用Python与Django框架构建,涵盖用户登录注册、电影信息管理、协同过滤推荐引擎、评分预测等核心… · 2026/9/23 13:43:27

HHA编码全解析:深度图如何化身三通道伪RGB助力RGB-D识别
HHA编码全解析:深度图如何化身三通道伪RGB助力RGB-D识别

做RGB-D识别的人,十有八九都遇到过这个问题:明明深度图就是个单通道的灰度距离图,为什么很多人非要把它变成HHA再喂给网络?HHA全称是Horizontal Disparity、Height above Ground、Angle with Gravity三个通道的缩写,最… · 2026/9/23 13:43:27

一次打包8大平台:oclif pack:tarballs跨平台打包与Node.js内嵌原理剖析
一次打包8大平台:oclif pack:tarballs跨平台打包与Node.js内嵌原理剖析

一次打包8大平台:oclif pack:tarballs跨平台打包与Node.js内嵌原理剖析 【免费下载链接】oclif CLI for generating, building, and releasing oclif CLIs. Built by Salesforce. 项目地址: https://gitcode.com/gh_mirrors/oc/oclif oclif 是 Salesforce 打… · 2026/9/23 13:43:20

光伏支架安装技术交底:测量控制与验收标准三大指标解析
光伏支架安装技术交底:测量控制与验收标准三大指标解析

简介:面向铅山5.3MW集中式光伏扶贫项目的工程技术交底文档,适合光伏施工管理人员、安装班组和安全质量人员使用。PDF全文围绕施工准备、施工机械设备配置、劳动力计划、施工工序及钢构安装工艺、质量保证措施等展开,明确测量放线、底梁横梁固… · 2026/9/23 14:30:18

打包英语源码拆解:3步搞定版本升级API变更的保姆级教程
打包英语源码拆解:3步搞定版本升级API变更的保姆级教程

打包英语源码拆解:3步搞定版本升级API变更的保姆级教程 版本升级后 API 全变了,报错堆栈看得人眼晕,是不是感觉之前的经验一夜作废?别慌,今天这篇【打包英语】源码解析就是为你准备的保姆级教程。我们直接撕开底层代码,看看那些让你头秃的接口… · 2026/9/23 14:30:10

Dota2启动不了?3个底层排查法,告别性能优化焦虑
Dota2启动不了?3个底层排查法,告别性能优化焦虑

Dota2启动不了?3个底层排查法,告别性能优化焦虑 刚把同事发来的启动脚本复制到本地,双击运行,黑窗口一闪而过,游戏图标还在,但就是进不去。你盯着屏幕,心里那股无名火蹭蹭往上冒:这代码看着挺规范,怎么到我这就跑不通?更让人头疼的是,为了排… · 2026/9/23 14:30:10

ABB IRC5 M2004 控制柜电路图深度解析:从读图到故障定位
ABB IRC5 M2004 控制柜电路图深度解析:从读图到故障定位

简介:ABB机器人IRC5 M2004控制器电路图是面向工业机器人电气设计、调试与维护人员的专业参考资料,适用于机器人控制系统架构学习、硬件选型与故障排查等场景。资源包内含1个PDF文件,整体约6.67MB,内容为ABB官方发布的IRC5 M2004控… · 2026/9/23 14:30:04

5分钟搞懂拯救公主:图解原理与实战避坑指南
5分钟搞懂拯救公主:图解原理与实战避坑指南

5分钟搞懂拯救公主:图解原理与实战避坑指南 官方文档翻了三遍,核心逻辑还是没抓住重点?这种“文档太长、重点模糊”的痛点,几乎是每个开发者入行时的必经之路。别急,今天咱们不背八股文,直接上 图解原理… · 2026/9/23 14:29:51

有担保的海外广告账户资源平台
有担保的海外广告账户资源平台

跨境出海投放过程中,不少企业在采购海外广告账户资源时,都遭遇过私域交易的各类风险:付款之后卖家失联、交付资产与描述不符、出现问题没有维权渠道。因此,是否具备正规交易担保机制,已经成为出海团队筛选资源平台的核… · 2026/9/23 14:29:51

3招搞定手机怎么下载微信面试难题实战项目解析
3招搞定手机怎么下载微信面试难题实战项目解析

3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03

你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型

你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29

Win7无线热点配置工具源码解析:解决API失效的3个实战技巧
Win7无线热点配置工具源码解析:解决API失效的3个实战技巧

Win7无线热点配置工具源码解析:解决API失效的3个实战技巧 Win7无线热点配置工具在Win10/11上跑不动?不是你的问题,是版本升级后 API 全变了。很多老项目里的 netsh wlan… · 2026/9/23 0:00:36

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码