MobX:observable.map存储对象与原对象无关联,如何实现同步行为?
解决MobX observable.map与原对象不同步的问题
这个问题的核心是MobX对存入observable.map()的普通JS对象的默认处理逻辑:当你把一个非observable的对象存入observable.map时,MobX会自动将其包装成一个新的observable对象——这个包装后的对象和你原来的user不是同一个引用,相当于做了一次浅复制,所以你修改原对象的属性,自然不会影响map里的那个副本。
下面给你三种可行的解决办法,你可以根据自己的需求选择:
方案一:先将原对象转为observable再存入map(推荐,支持响应式)
如果需要保持对象的响应式能力(比如后续修改属性能触发autorun、组件更新等),这是最优方案:
import { configure, observable, action } from 'mobx'; configure({ enforceActions: true }); // 先把普通对象转为observable对象 let user = observable({id: 1, name: "John"}); let myMap = observable.map(); myMap.set(user.id, user); // 注意:开启enforceActions后,修改observable属性必须放在action中 action(() => { user.name = "Bill"; })(); console.log(myMap.get(1).name); // 现在输出Bill
因为user本身就是observable对象,存入map时MobX不会再创建新的包装对象,而是直接存储原引用,所以修改user的属性会同步反映到map里的对象上,同时还能正常触发MobX的响应式更新。
方案二:禁止observable.map自动包装对象(仅需引用同步,无需响应式)
如果不需要响应式,只是想让map里的对象和原对象保持引用同步,可以给observable.map()传入{ deep: false }配置,关闭自动包装逻辑:
import { configure, observable } from 'mobx'; configure({ enforceActions: true }); let user = {id: 1, name: "John"}; // 配置deep: false,直接存储原对象引用 let myMap = observable.map({}, { deep: false }); myMap.set(user.id, user); user.name = "Bill"; console.log(myMap.get(1).name); // 输出Bill
这种方式下,map里存储的就是原对象的引用,修改原对象自然会同步到map中,但因为对象本身不是observable的,后续修改属性不会触发MobX的响应式机制。
方案三:修改后重新存入map(兜底方案,不推荐)
如果必须保留原对象为普通对象,又需要临时同步,可以在修改原对象后,重新把它set回map里:
import { configure, observable, action } from 'mobx'; configure({ enforceActions: true }); let user = {id: 1, name: "John"}; let myMap = observable.map(); myMap.set(user.id, user); action(() => { user.name = "Bill"; // 重新set覆盖原有值,实现同步 myMap.set(user.id, user); })(); console.log(myMap.get(1).name); // 输出Bill
这个方法比较繁琐,而且每次修改都要手动同步,容易遗漏,所以只建议作为临时兜底方案使用。
内容的提问来源于stack exchange,提问作者cdarwin
相关产品推荐
相关产品推荐

