State、event、navigation
Reactive store
Apsuleでは概念上3つのscopeを使います。
| Scope | Lifetime | 主な用途 |
|---|---|---|
state | View/component runtime | UI state、loading flag、現在のlist data。 |
global | 実行中Apsule Project | routeをまたぐsession/account/shared state。 |
storage | Persistent | process/project再起動後も残る設定やデータ。魔法のような同期disk writeではなくHost API経由でアクセスする。 |
stateとglobalの変更はreactiveです。
state.loading = true;
global.currentUser = user;bindされたSwiftUI nodeは自動更新されます。
Action
JSONは名前付きactionを参照し、任意のJavaScriptを直接含めません。
{
"id": "refresh",
"type": "Button",
"props": { "text": "Refresh" },
"events": {
"tap": { "action": "refreshMatches" }
}
}actions.refreshMatches = async () => {
state.loading = true;
try {
state.matches = await api.getMatches();
} finally {
state.loading = false;
}
};Actionは任意のevent payloadを最初のJavaScript引数として受け取れます。通常のstatic controlは現在、domain dataなしでactionを呼び出します。ForEach内で描画されたcontrolは現在のiteration scopeを受け取るため、各rowごとに別のstatic actionを作らなくても、actionからevent.match.idやevent.item.contentなどを参照できます。
entry viewにはappear actionを定義できます。Hostは実行中Projectのrootが表示されたとき、通常のPromise-aware action pathからこれを呼び出します。そのため、非同期cache loadや、stateをSwiftUIへ反映する必要がある初期同期を行う場所として適しています。
Event vocabulary
実装済みのevent vocabularyには次が含まれます。
appeardisappearforegroundinactivebackgroundtapdoubleTaplongPresschangesubmitrefreshdragdropswipefocusblurconfirmreordercontextnavigateerrormessageregionChangemapTap- 外部lifecycle event向けのtop-level action
openURL、notification、push
Event payloadはJSON-serializableです。gesture/map/web event固有のfieldはevent配下に置かれ、ForEachでは現在のiteration scopeも保持されます。
Navigation
viewの各所へfilesystem pathを埋め込むより、route nameを利用します。
{
"routes": {
"home": "views/home.json",
"player": "views/player.json"
}
}JavaScript API:
router.push("player", { id: player.id });
router.pop();
router.replace("home");
router.sheet("settings");
router.dismiss();上記JavaScript routerは実装済みです。Route parameterはstate/globalへコピーしない限り、route.params scopeにあるread-only inputとして扱われます。宣言的なNavigationLinkもprops.paramsを受け取れます。
Hostはさらにapsule:// deep-link schemeを処理します。実行中Projectは通常の外部URLをactions.openURL(payload)で受け取ります。scene transitionではtop-levelのactions.foreground、actions.inactive、actions.backgroundを呼び出します。Project push notificationはProjectがpush permissionを宣言し承認されている場合にのみactions.push(payload)を呼び出し、local notificationのtapはactions.notification(payload)を呼び出します。
このroute modelは、将来Apsule Builderにvisual navigation graphを追加する場合にも適しています。
Subscription
長時間動作するHost API operationはcancel可能なsubscriptionを返します。
const sub = host.location.watch(position => {
global.position = position;
});
// Later
sub.cancel();runtimeは、明示的にapp scopeへ昇格された場合を除き、所有viewが破棄された時点でview-scoped subscriptionを自動解放する必要があります。