Gelişmiş
Frame
Tek bir değişen içeriği tutan kapsayıcı; navigate ile içerik değişimi, zamanlama, çıkış geçişleri ve çerçevenin Frame kurduğu yerler.
Koşullu dallar (&&, üçlü operatör, switch), {() => ifade} biçimindeki getter çocuklar ve rota sayfaları aynı yapı üstünde çalışır: tek bir içeriği tutan ve değiştiren bir kapsayıcı. Bu kapsayıcı Frame'dir. Frame, kökü bir yorum düğümü olan (DOM'a eleman eklemeyen) bir bileşendir; içinde her an en fazla bir içerik (bileşen ya da bileşen dizisi) bulunur, navigate ile içerik değiştirilir, eskisi serbest bırakılır.
Kullanım
Örnekteki özet paneli, iki düğmeyle son notlar listesi (RecentNotes) ile klasör grafiği (FolderChart) arasında geçer:
import { Component, Frame } from "@motifx/core";
import { FolderChart } from "./FolderChart";
import { RecentNotes } from "./RecentNotes";
export class SummaryPanel extends Component<HTMLElement> {
static override elementTag = "section";
frame = new Frame();
override onConfigured() {
this.frame.navigate(<RecentNotes />);
}
override view() {
return (
<>
<button type="button" onclick={() => this.frame.navigate(<RecentNotes />)}>Son notlar</button>
<button type="button" onclick={() => this.frame.navigate(<FolderChart />)}>Klasörler</button>
{this.frame}
</>
);
}
}
import { Component, ComponentBase, Frame, motifComponent, motifFragment } from "@motifx/core";
import { FolderChart } from "./FolderChart";
import { RecentNotes } from "./RecentNotes";
export class SummaryPanel extends Component<HTMLElement> {
static override elementTag = "section";
frame = new Frame();
override onConfigured() {
this.frame.navigate(new RecentNotes());
}
override view() {
const recent = motifComponent("button", (button: ComponentBase) => {
button.attr.add({ type: "button" });
button.motif.on("click", () => this.frame.navigate(new RecentNotes()));
button.setText("Son notlar");
});
const folders = motifComponent("button", (button: ComponentBase) => {
button.attr.add({ type: "button" });
button.motif.on("click", () => this.frame.navigate(new FolderChart()));
button.setText("Klasörler");
});
return motifFragment({ childs: [recent, folders, this.frame] });
}
}
import { Frame } from "@motifx/core";
import { FolderChart } from "./FolderChart";
import { RecentNotes } from "./RecentNotes";
export function SummaryPanel() {
const frame = new Frame();
frame.navigate(<RecentNotes />);
return (
<section>
<button type="button" onclick={() => frame.navigate(<RecentNotes />)}>Son notlar</button>
<button type="button" onclick={() => frame.navigate(<FolderChart />)}>Klasörler</button>
{frame}
</section>
);
}
import { ComponentBase, Frame, motifComponent } from "@motifx/core";
import { FolderChart } from "./FolderChart";
import { RecentNotes } from "./RecentNotes";
export function SummaryPanel() {
const frame = new Frame();
frame.navigate(motifComponent(RecentNotes));
return motifComponent("section", (section: ComponentBase) => {
const recent = motifComponent("button", (button: ComponentBase) => {
button.attr.add({ type: "button" });
button.motif.on("click", () => frame.navigate(motifComponent(RecentNotes)));
button.setText("Son notlar");
});
const folders = motifComponent("button", (button: ComponentBase) => {
button.attr.add({ type: "button" });
button.motif.on("click", () => frame.navigate(motifComponent(FolderChart)));
button.setText("Klasörler");
});
section.controls.add(recent, folders, frame);
});
}
import { Frame, motifOptions } from "@motifx/core";
import { FolderChart } from "./FolderChart";
import { RecentNotes } from "./RecentNotes";
export const SummaryPanel = () => motifOptions({
el: "section",
frame: new Frame(),
onConfigured() {
this.frame.navigate(<RecentNotes />);
},
view() {
return (
<>
<button type="button" onclick={() => this.frame.navigate(<RecentNotes />)}>Son notlar</button>
<button type="button" onclick={() => this.frame.navigate(<FolderChart />)}>Klasörler</button>
{this.frame}
</>
);
},
});
import { ComponentBase, Frame, motifComponent, motifFragment, motifOptions } from "@motifx/core";
import { FolderChart } from "./FolderChart";
import { RecentNotes } from "./RecentNotes";
export const SummaryPanel = () => motifOptions({
el: "section",
frame: new Frame(),
onConfigured() {
this.frame.navigate(motifComponent(RecentNotes));
},
view() {
const recent = motifComponent("button", (button: ComponentBase) => {
button.attr.add({ type: "button" });
button.motif.on("click", () => this.frame.navigate(motifComponent(RecentNotes)));
button.setText("Son notlar");
});
const folders = motifComponent("button", (button: ComponentBase) => {
button.attr.add({ type: "button" });
button.motif.on("click", () => this.frame.navigate(motifComponent(FolderChart)));
button.setText("Klasörler");
});
return motifFragment({ childs: [recent, folders, this.frame] });
},
});
import { Component, Frame } from "@motifx/core";
import { FolderChart } from "./FolderChart";
import { RecentNotes } from "./RecentNotes";
export class SummaryPanel extends Component {
static elementTag = "section";
frame = new Frame();
onConfigured() {
this.frame.navigate(<RecentNotes />);
}
view() {
return (
<>
<button type="button" onclick={() => this.frame.navigate(<RecentNotes />)}>Son notlar</button>
<button type="button" onclick={() => this.frame.navigate(<FolderChart />)}>Klasörler</button>
{this.frame}
</>
);
}
}
import { Component, Frame, motifComponent, motifFragment } from "@motifx/core";
import { FolderChart } from "./FolderChart";
import { RecentNotes } from "./RecentNotes";
export class SummaryPanel extends Component {
static elementTag = "section";
frame = new Frame();
onConfigured() {
this.frame.navigate(new RecentNotes());
}
view() {
const recent = motifComponent("button", (button) => {
button.attr.add({ type: "button" });
button.motif.on("click", () => this.frame.navigate(new RecentNotes()));
button.setText("Son notlar");
});
const folders = motifComponent("button", (button) => {
button.attr.add({ type: "button" });
button.motif.on("click", () => this.frame.navigate(new FolderChart()));
button.setText("Klasörler");
});
return motifFragment({ childs: [recent, folders, this.frame] });
}
}
import { Frame } from "@motifx/core";
import { FolderChart } from "./FolderChart";
import { RecentNotes } from "./RecentNotes";
export function SummaryPanel() {
const frame = new Frame();
frame.navigate(<RecentNotes />);
return (
<section>
<button type="button" onclick={() => frame.navigate(<RecentNotes />)}>Son notlar</button>
<button type="button" onclick={() => frame.navigate(<FolderChart />)}>Klasörler</button>
{frame}
</section>
);
}
import { Frame, motifComponent } from "@motifx/core";
import { FolderChart } from "./FolderChart";
import { RecentNotes } from "./RecentNotes";
export function SummaryPanel() {
const frame = new Frame();
frame.navigate(motifComponent(RecentNotes));
return motifComponent("section", (section) => {
const recent = motifComponent("button", (button) => {
button.attr.add({ type: "button" });
button.motif.on("click", () => frame.navigate(motifComponent(RecentNotes)));
button.setText("Son notlar");
});
const folders = motifComponent("button", (button) => {
button.attr.add({ type: "button" });
button.motif.on("click", () => frame.navigate(motifComponent(FolderChart)));
button.setText("Klasörler");
});
section.controls.add(recent, folders, frame);
});
}
import { Frame, motifOptions } from "@motifx/core";
import { FolderChart } from "./FolderChart";
import { RecentNotes } from "./RecentNotes";
export const SummaryPanel = () => motifOptions({
el: "section",
frame: new Frame(),
onConfigured() {
this.frame.navigate(<RecentNotes />);
},
view() {
return (
<>
<button type="button" onclick={() => this.frame.navigate(<RecentNotes />)}>Son notlar</button>
<button type="button" onclick={() => this.frame.navigate(<FolderChart />)}>Klasörler</button>
{this.frame}
</>
);
},
});
import { Frame, motifComponent, motifFragment, motifOptions } from "@motifx/core";
import { FolderChart } from "./FolderChart";
import { RecentNotes } from "./RecentNotes";
export const SummaryPanel = () => motifOptions({
el: "section",
frame: new Frame(),
onConfigured() {
this.frame.navigate(motifComponent(RecentNotes));
},
view() {
const recent = motifComponent("button", (button) => {
button.attr.add({ type: "button" });
button.motif.on("click", () => this.frame.navigate(motifComponent(RecentNotes)));
button.setText("Son notlar");
});
const folders = motifComponent("button", (button) => {
button.attr.add({ type: "button" });
button.motif.on("click", () => this.frame.navigate(motifComponent(FolderChart)));
button.setText("Klasörler");
});
return motifFragment({ childs: [recent, folders, this.frame] });
},
});
JSX'te <Frame>…</Frame> arasına yazılan çocuklar, JSX'siz yazımda new Frame({ childs: [...] }) ile verilenler ilk içerik olur. navigate'e bir Promise verilirse içerik Lazy ile yüklenir.
API
| Üye | Açıklama |
|---|---|
new Frame(props?) |
Boş kapsayıcı. props.childs verilirse (JSX'te <Frame>…</Frame>) çocuklar ilk içerik olarak eklenir. |
navigate(page, keepOldControl?) |
page bir bileşen, bileşen dizisi, bileşen sınıfı/fabrikası ya da bir Promise olabilir. Eski içerik serbest bırakılır (keepOldControl: true verilirse yerinde kalır), yenisi eklenir. Promise verilirse içerik Lazy ile yüklenir; bir sonraki navigate önceki yüklemeyi iptal eder. Aynı içerikle ikinci çağrı hiçbir şey yapmaz. Döndürdüğü Promise içerik yerleştiğinde çözülür. |
navigateLazy(caller, options?, keepOldControl?) |
navigate(Lazy({ caller, options })) kısa yazımı. |
flush() |
Mevcut içeriği serbest bırakır; kapsayıcı boş kalır. motif.clear() da aynı işi yapar. |
current |
Gösterilen içerik (ComponentBase, dizi ya da null). |
isBusy |
Bir navigate sürüyorken true. |
dispose(options?) |
Önce içeriği, sonra kapsayıcıyı serbest bırakır; options içeriğe de iletilir. |
Zamanlama
- İlk içerik senkrondur. Kapsayıcı boşken ve
pagebirPromisedeğilkennavigatedöndüğünde içerik yerleşmiştir;build()tamamlandığında ilk dal ekrandadır (bkz. Koşullu gösterim - Senkron ilk çizim). - Sonraki değişimler sıralıdır. Art arda
navigateçağrıları bir kilitle sıraya girer; her biri öncekinin bitmesini bekler. Araya giren yeni bir çağrı, henüz yerleşmemiş eski çağrının sonucunu düşürür (yalnız en son istenen içerik yerleşir). - Çıkış geçişi olmayan eski içerik serbest bırakıldıktan (
onDisposed) sonra yeni içerik eklenir. - İçerik yerleştirilemezse
MJX114, eski içerik serbest bırakılamazsaMJX115raporlanır; kapsayıcı çalışmaya devam eder.
Çıkış ve giriş geçişleri
Eski içerik çıkış geçişini oynatır: önce süren animasyonları iptal edilir, sonra dispose({ deep: true }) ile serbest bırakılır; çıkış geçişi tanımlıysa (transition prop'u ya da motif.options.transition.out(...)) oynar. Yeni içerik eski içeriğin bitmesini beklemez: eski içerik çıkarken yenisi hemen eklenir ve ikisinin sırası en yakın eleman ebeveynin mode'una göre belirlenir (bkz. Stil ve animasyon - Giriş ve çıkış sırası):
mode |
Davranış |
|---|---|
'concurrent' (varsayılan) |
Eski içerik çıkarken yeni içerik aynı anda girer. |
'out-in' |
Yeni içerik, eskinin çıkışı bitene kadar DOM'a yerleşmez. |
'in-out' |
Eskinin çıkışı, yeninin girişi bitene kadar ertelenir. |
Frame yorum düğümlü olduğundan kipi kendisi taşımaz; en yakın eleman ebeveyninkini kullanır. Kipi taşıyan bir elemanın içindeki koşullu dal da iç içe Frame'lerden geçerek aynı kipi kullanır.
dispose(), flush() ve motif.clear() de içeriğin çıkış geçişini oynatır ve bitmesini bekler; dispose({ skipLeaveTransition: true }) içeriğe de aynı seçenekle iletilir.
Çerçevenin Frame kurduğu yerler
Çerçeve Frame'i şu yerlerde kendisi kurar: {koşul && <X/>} (bindings.when), üçlü operatör (bindings.ternary), switch (bindings.switchCase), bileşen döndüren {() => …} çocuklar (bindings.method) ve Lazy. RouterView ayrı bir bileşendir ama sayfa değişiminde aynı gezinme mantığını (sıralı kilit, Promise için Lazy) kullanır; farkı, ayrılan sayfanın serbest bırakılmasını beklememesidir (bkz. Ayrılan sayfa). Bunun dışında yukarıdaki kurallar hepsi için geçerlidir.
Sonraki adım
Dinamik import() ile içerik için Lazy; dal değişimlerinin kullanım tarafı için Koşullu Gösterim ve Listeler.