Rehberler
Motif Üstüne Paket Yazmak
Derleyici çıktısının çerçevenin açık API'si olması; tema, katman, yerleşim, kabuk ve eklenti, veri, sarmalayıcı, ayar ve geçiş paketlerinin hangi mekanizmaya dayandığı.
Bir MotifJS paketi uygulama koduyla aynı malzemeden yapılır: bileşenler, servisler ve reaktif nesneler. Paketin JSX ile mi JSX'siz mi yazıldığı onu kullanan uygulamayı ilgilendirmez, çünkü derleyicinin JSX'ten ürettiği kod da çerçevenin herkese açık API'sidir; arada ayrı bir şablon temsili yoktur.
Derleyici çıktısı
Not listesinden şu parçayı derleyici aşağıdaki tablodaki çağrılara çevirir:
Not listesinden şu parça, aynı parçanın JSX yazımından derleyicinin ürettiği çağrıların elle yazılmış hâlidir; tablo iki yazımı satır satır eşler:
<section class="list">
<h2>{folder.title}</h2>
<p x-wait={() => !state.loading}>Notlar yükleniyor…</p>
<ul>
{state.items.map((note) => (
<li key={note.id} class={note.pinned ? "pinned" : ""}>{note.title}</li>
))}
</ul>
</section>
const list = motifComponent("section", (section: ComponentBase) => {
section.class.add("list");
const title = motifComponent("h2", (h2: ComponentBase) => {
h2.controls.add(motifComponent("text", (node: ComponentBase) => node.bindings.add("textContent", folder, "title")));
});
const loading = motifComponent("p", {
preconfig: (p: ComponentBase) => p.bindings.wait(() => !state.loading),
initializeComponent: (p: ComponentBase) => p.controls.add(motifComponent("text", (node: ComponentBase) => node.setText("Notlar yükleniyor…"))),
});
const items = motifComponent("ul", (ul: ComponentBase) => {
ul.controls.add(motifComponent({
initializeComponent: (holder: ComponentBase) => holder.bindings.list(() => state.items, (note: Note) => motifComponent("li", {
indexkey: () => note.id,
initializeComponent: (li: ComponentBase) => {
li.class.add([() => (note.pinned ? "pinned" : "")]);
li.controls.add(motifComponent("text", (node: ComponentBase) => node.bindings.add("textContent", note, "title")));
},
})),
}));
});
section.controls.add(title, loading, items);
});
<section class="list">
<h2>{folder.title}</h2>
<p x-wait={() => !state.loading}>Notlar yükleniyor…</p>
<ul>
{state.items.map((note) => (
<li key={note.id} class={note.pinned ? "pinned" : ""}>{note.title}</li>
))}
</ul>
</section>
const list = motifComponent("section", (section) => {
section.class.add("list");
const title = motifComponent("h2", (h2) => {
h2.controls.add(motifComponent("text", (node) => node.bindings.add("textContent", folder, "title")));
});
const loading = motifComponent("p", {
preconfig: (p) => p.bindings.wait(() => !state.loading),
initializeComponent: (p) => p.controls.add(motifComponent("text", (node) => node.setText("Notlar yükleniyor…"))),
});
const items = motifComponent("ul", (ul) => {
ul.controls.add(motifComponent({
initializeComponent: (holder) => holder.bindings.list(() => state.items, (note) => motifComponent("li", {
indexkey: () => note.id,
initializeComponent: (li) => {
li.class.add([() => (note.pinned ? "pinned" : "")]);
li.controls.add(motifComponent("text", (node) => node.bindings.add("textContent", note, "title")));
},
})),
}));
});
section.controls.add(title, loading, items);
});
| JSX ifadesi | Derlendiği çağrı | İzlenen |
|---|---|---|
class="list" |
section.class.add("list") |
yok; bir kez yazılır |
{folder.title} |
metin düğümünde node.bindings.add("textContent", folder, "title") |
yalnız folder.title |
x-wait={() => !state.loading} |
p.bindings.wait(() => !state.loading), eleman kurulmadan önce (preconfig) |
getter'ın okuduğu her alan |
{state.items.map(…)} |
elemansız tutucuda holder.bindings.list(() => state.items, (note) => motifComponent("li", …)) |
dizinin uzunluğu ve öğe kimliği |
key={note.id} |
indexkey: () => note.id |
— |
class={note.pinned ? "pinned" : ""} |
li.class.add([() => (note.pinned ? "pinned" : "")]) |
getter'ın okuduğu her alan |
| her eleman | motifComponent("h2", …) ve ebeveynde controls.add(h2) |
— |
Sağ sütundaki çağrılar JSX'siz yazımın kendisidir (bkz. JSX'siz Görünümler). Bir dosyanın bu tablosunu @motifx/compiler ile gelen motif-explain verir; --code üretilen kodun tamamını da yazar:
npx motif-explain src/parts/NoteList.tsx
Bu yüzden bir paket kendi bileşenlerini hangi yazımla yazarsa yazsın, uygulama onları aynı yollarla kullanır: JSX'te etiketle (<NoteList />), JSX'siz yazımda sınıf için new NoteList(props), fonksiyon ve Options için motifComponent(NoteList, props).
Paket türleri
Aşağıdaki türlerin her biri çekirdekteki bir mekanizmaya dayanır; ayrıntı o mekanizmanın sayfasındadır.
Tema ve tasarım sistemi
Tema bileşenlerin değil belgenin özelliğidir. Seçili tema ve yoğunluk bir singleton serviste reaktif durum olarak tutulur; servis bunu <html> elemanına öznitelik olarak yazar (data-theme), CSS de özniteliği okur. Servis startup: true ile kaydedilirse hiçbir bileşen onu istemeden uygulama açılırken çalışır (bkz. Başlangıçta oluşturulan singleton'lar). Bir alt ağacın farklı görünmesi gerekiyorsa aynı öznitelik o ağacın kök elemanına yazılır; ayrı bir servis kapsamı gerekmez.
Paketin CSS'i bir @layer içinde gelir: katmansız bir kural, uygulamanın bütün katmanlı kurallarını özgüllükten bağımsız ezer (bkz. Stil ve CSS).
İletişim kutusu, bildirim ve açılır katman
Bir iletişim kutusu onu açan bileşenin parçasıdır ama sayfanın en üst katmanında görünmelidir. Katman çekirdekte hazırdır: app.layer <body>'nin sonundaki katman bileşenidir, app.layerOf(açan) açan bileşen bir penceredeyse o pencerenin katmanını verir (bkz. Sayfa katmanı). Paket kutuyu this.context.layerOf(this, kutu) ile doğrudan koyabilir; o zaman kutunun ömrü katmanındır ve kapanınca kaldırmak paketin işidir (remove ya da kutunun kendi dispose'u). Kutunun açan bileşenle birlikte kalkması gerekiyorsa paket katmana bir Transport yuvası koyar ve içeriği açan bileşenin içinde bir TransportTo ile yazar: içerik yuvada görünür, bağları ve olay işleyicileri yazıldığı bileşenin durumuyla çalışır, açan bileşen serbest bırakılınca içerik de yuvadan kalkar. Bildirimlerin aynı yuvada birikmesi için yuva mode: "merge" ile kurulur (bkz. Transport ve TransportTo).
Yerleşim ve panel taşıma
Bölme, sekme ve yanaşan panel paketlerinde bir panel bir bölgeden ötekine taşınır ama durumunu kaybetmemelidir. Bileşen başka bir ebeveynin controls.add'ine verilince eski ebeveyninden kendiliğinden ayrılır; serbest bırakılmaz, bağları ve durumu yerinde kalır. DOM'dan söküldüğünde onDeactivated, yeniden yerleşince onActivated alır (bkz. Serbest bırakmadan taşıma). Aynı taşımayı Transporter.transport da yapar (bkz. Programatik taşıma). Rota sayfası olan bir panelin örneğini gezinmeler arasında keepAlive: true korur (bkz. Rota Tanımları).
Uygulama kabuğu ve eklentiler
Kabuk paketi uygulamanın iskeletini verir: kenar çubuğu, araç çubuğu, durum satırı. Eklentiler bu iskelete parça ekler. İskeletin her bölgesi adlı bir Transport yuvasıdır; eklenti kendi bileşeninde aynı adlı bir TransportTo ile o bölgeye içerik gönderir. Yuvanın gönderenden önce ya da sonra kurulması sonucu değiştirmez. Eklentinin servisleri uygulamanın ServiceCollection'ına kaydedilir, kabuk onları sağlayıcıdan alır (bkz. Servis Kaydı).
Veri bileşenleri
Tablo, ızgara ve uzun liste paketlerinde liste bağı satırı key ile değil öğe nesnesiyle tanır: aynı nesne yeni sıraya geçince satırı taşınır, yeniden kurulmaz (bkz. key ve öğe kimliği). Binlerce satır ya da sunucudan sayfa sayfa gelen veri için Virtualization yalnız görünen satırları kurar ve veriyi dataRequest ile ister (bkz. Sanal Listeler).
Kütüphane sarmalayıcıları
Kendi DOM'unu yöneten bir kütüphane (grafik, harita, editör) bileşenin elemanına kurulur. Kurulum onBuilt ya da initializeComponent içinde yapılır, kütüphanenin kendi temizliği motif.setDisposable ile bileşene bağlanır. Kuralların tamamı Üçüncü Parti Kütüphane Sarmalama sayfasındadır.
Dil ve kullanıcı ayarları
Dil, saat dilimi ve yoğunluk gibi ayarlar tek bir singleton serviste reaktif nesne olarak durur. Bileşenler değeri bir bağın içinde okur; ayar değişince yalnız o değeri okuyan bağlar yenilenir, bileşenler yeniden kurulmaz (bkz. Reaktivite, Yaşam Süreleri ve Kapsamlar).
Geçiş paketleri
Geçiş paketi CSS sınıf adları ve keyframe tanımları verir. Sınıf tabanlı geçiş transition adıyla bağlanır (fade → fade-enter-from …), kodla tanımlanan animasyon motif.options.transition.in / out ile verilir. Giriş ve çıkışın sırasını uygulama app.useTransitions({ mode }) ile belirler (bkz. Stil ve Animasyon).
Paketi yayımlamak
Paket biçimi, derleme, tipler, CSS, prop sözleşmesi ve yayın denetimi MotifJS için npm Kütüphanesi Yayımlama sayfasındadır. Derlenmiş JSX taşıyan paket, kullanıldığı @motifx/core'un desteklediği bir derleyici sözleşmesiyle derlenmiş olmalıdır; desteklenmeyen sözleşmede geliştirme modunda MJX121 uyarısı yazılır.
Sonraki adım
Kendi DOM'unu yöneten bir kütüphaneyi bileşene dönüştürmek için Üçüncü Parti Kütüphane Sarmalama bölümüne geçin.