用法:
action(fn)
action(name, fn)
@action classMethod() {}
@action(name) classMethod () {}
@action boundClassMethod = (args) => { body }
@action(name) boundClassMethod = (args) => { body }
@action.bound classMethod() {}
@action.bound(function() {})
任何应用都有行为。任何改变状态的代码都称为行为。
使用MobX可以使你的代码更加清晰,Action会使你的代码结构更优。
它获得一个函数,并将这个函数使用 untracked
, transaction
and allowStateChanges
包裹后返回。
建议在任何改变状态或具有副作用的函数上使用。也提供了有效的调试信息。
不支持在 ES 5.1 setters (i.e. @action set propertyName
) 使用 @action
, 即使计算值自动触发action.
注意:当严格模式开启时。使用 action
是强制的。请查阅 useStrict
可以查看关于action
的进一步介绍 MobX 2.2 release notes.
两个来自于『通讯录』项目的例子:
@action createRandomContact() {
this.pendingRequestCount++;
superagent
.get('https://randomuser.me/api/')
.set('Accept', 'application/json')
.end(action("createRandomContact-callback", (error, results) => {
if (error)
console.error(error);
else {
const data = JSON.parse(results.text).results[0];
const contact = new Contact(this, data.dob, data.name, data.login.username, data.picture)
contact.addTag('random-user');
this.contacts.push(contact);
this.pendingRequestCount--;
}
}));
}
async
行为 和runInAction
action
只影响当前运行的函数,不是当前被调度(不是调用)的函数。也就是说,如果你有一个setTimeOut
,promise .then
或 async
构造,在回调中有更多的状态被该改变,这些回调也应该被包含在 action
中。这可以在上面的 "createRandomContact-callback"
操作来演示。
如果你使用 async/await
,这就非常棘手了,因为你不能只是在 action
中单纯的包装异步函数体了。在这种情况下, runInAction
就可以派上用场了,在你打算更新状态的地方使用它就可以了。(但是不要在 await
中调用这些区块)
例如:
@action /*可选的*/ updateDocument = async () => {
const data = await fetchDataFromUrl();
/* 在严格模式下是强制的: */
runInAction("update state after fetching data", () => {
this.data.replace(data);
this.isSaving = true;
})
}
runInAction
的用法是: runInAction(name?, fn, scope?)
.
如果你使用babel,这个插件可以帮助你处理你的异步行为:MobX-deep-action.
action
装饰器 / 函数使用javascript通常的绑定(binding)规则。
而MobX3 引入了action.bound
以自动地将action与目标对象绑定。
注意(@)action.bound
与 action
不同,不需要一个name参数,这个名称与action绑定的属性相同。
例如:
class Ticker {
@observable this.tick = 0
@action.bound
increment() {
this.tick++ // 上下文永远是正确的
}
}
const ticker = new Ticker()
setInterval(ticker.increment, 1000)
Or
const ticker = observable({
tick: 1,
increment: action.bound(function() {
this.tick++ // 绑定上下文
})
})
setInterval(ticker.increment, 1000)
注意:不要将 action.bind 与箭头函数组合使用,因为箭头函数已经绑定上下文,且不能重新绑定