MobX懒行为实现及代码问题:autorun不触发、useStrict规则疑问
嘿,我来帮你拆解这几个MobX的问题,一个个捋清楚:
_userArrayRev触发重新计算,让autorun生效 首先,MobX里的“懒行为/延迟计算”得靠computed来实现,它天生就是懒加载的——只有当被观察(比如在autorun里访问)时才会计算,而且依赖的可观察变量变化时会自动重新计算。你之前的_userArrayRev如果是普通变量,MobX根本不知道它和userArray的依赖关系,自然不会更新。
正确的做法是把_userArrayRev定义成computed属性:
// 假设你用类的写法 class Store { @observable userArray = []; // 用@computed标记这是一个计算属性 @computed get userArrayRev() { console.log('重新计算反转数组'); return this.userArray.slice().reverse(); } }
然后关键是在autorun的回调里必须访问这个computed属性,这样autorun才会建立和它的依赖关系:
autorun(() => { // 这里一定要用到userArrayRev,不然autorun根本不知道要追踪它 console.log('反转后的列表:', store.userArrayRev); });
这样每次userArray变化,userArrayRev会自动重新计算,autorun也会跟着触发。
autorun预期执行3次,实际只跑了1次 结合上面的点,大概率是这几个原因:
autorun里没访问computed属性:如果你的autorun回调里根本没碰_userArrayRev,那它只会在初始化时执行一次,之后不管userArray怎么变都不会触发。_userArrayRev不是computed变量:普通变量不会自动更新,依赖变化时它的值还是老的,autorun没理由重新执行。- 修改
userArray的方式不对:如果你的userArray是observable数组,但你直接替换数组(比如this.userArray = [...this.userArray, '新用户'])而不用MobX提供的数组方法(push/splice/replace),MobX追踪不到变化,自然不会触发更新。
另外要注意:autorun默认会立即执行一次,如果你预期的3次是指调用3次AddUser对应的触发,那实际会是4次(初始化1次+3次更新)。如果想去掉初始化的那次,可以用reaction代替,它只在依赖变化时触发。
useStrict(true)(enforceActions)后,AddUser()里能修改userArray 首先,新版MobX里useStrict(true)已经被configure({ enforceActions: "always" })替代了,但核心规则没变:只有在action函数内部才能修改可观察变量。
你能在AddUser()里修改成功,肯定是因为这个函数被MobX标记成action了:
- 要么是用
@action装饰器(比如@action AddUser() { ... }) - 要么是用
action()函数包裹(比如const AddUser = action(() => { ... }))
如果你的AddUser没被action装饰,开启严格模式后应该会直接报错,提示你不能在action外修改可观察变量。所以检查一下你的AddUser是不是被正确标记成action了。
最后给你一个完整的修正示例,你可以直接参考:
import { observable, computed, autorun, action, configure } from 'mobx'; // 启用严格模式,强制所有修改必须在action内 configure({ enforceActions: "always" }); class UserStore { @observable userArray = []; // 延迟计算的反转数组 @computed get userArrayRev() { return this.userArray.slice().reverse(); } // 标记为action,允许修改可观察变量 @action AddUser(name) { this.userArray.push(name); } } const store = new UserStore(); // autorun会追踪userArrayRev的依赖 autorun(() => { console.log('反转后的用户列表:', store.userArrayRev); }); // 调用3次AddUser,autorun会触发3次更新(加上初始化共4次) store.AddUser('用户1'); store.AddUser('用户2'); store.AddUser('用户3');
内容的提问来源于stack exchange,提问作者cdarwin

