İçindekiler
Bileşenler
Carats bileşenleri React bileşenlerine benzer, ancak öznitelik ve olayları ele alış biçiminde önemli farklar vardır.
Bileşen Yapısı
Bileşenler, varsayılan bir fonksiyon dışa aktaran .tsx dosyalarıdır. Tek bir props nesnesi alırlar, defaultProps tanımlayabilirler ve çocukların görünmesi gereken yerde props.children işlerler. Vite'in anladığı her dosyayı içe aktarabilirler; SASS'in bir bileşene bağlanması da bu yolla olur.
import './_layout.sass';
export default function Layout(props: JSX.ComponentProps) {
return (
<>
<header>Hello World</header>
<main>{props.children}</main>
<footer>Carats</footer>
</>
)
}
Örnek Bileşen
import './home.sass';
export default function Home() {
return (
<div class="home">
<h1>Welcome to Carats</h1>
<p>Build amazing applications with JJSX</p>
</div>
);
}
SASS dosyası yan etkisi için içe aktarılır; stil dosyasını sayfaya bağlayan şey budur. Bir bileşen Vite'in anladığı her şeyi içe aktarabilir: SASS, CSS, JSON veya görseller.
Prop'lar ve Çocuklar
Prop'lar bileşenlere beklendiği gibi geçirilir ve çocuklar bileşen etiketleri içinde bulunur. Burnished bir bileşen ise bunun yerine culet'inin dönüş değerini prop olarak alır.
export default function Card(props: { title: string; children?: JSX.Element }) {
return (
<article class="card">
<h2>{props.title}</h2>
{props.children}
</article>
);
}
// Usage
<Card title="My Card">
<p>Card content here</p>
</Card>
Varsayılan Prop'lar
defaultProps, verilmemiş prop'ları doldurur. Bir sayfayı sunucu prop'larının bulunmadığı testlerde işlenebilir hâle getirmenin yaygın yoludur.
import { CaratsComponent } from '@carats/render';
const Profile: CaratsComponent<User> = function (user) {
return <h1>{user.name}</h1>;
};
Profile.defaultProps = {
id: '0',
name: 'Guest',
username: 'guest',
email: '',
phone: '',
website: ''
};
export default Profile;
Dinamik Head Etiketleri
Bileşenler, bileşen fonksiyonu içinde this.head'e atama yaparak dinamik head etiketleri (title, meta) sağlayabilir. Etiketler sunucu tarafı işleme sırasında toplanır ve HTML şablonundaki <!--app-head--> yer tutucusuna eklenir.
import { CaratsComponent } from '@carats/render';
export default function Home(this: CaratsComponent) {
this.head = <>
<title>Home Page</title>
<meta name="description" content="Welcome to my app" />
</>;
return <div>Home</div>;
}
this yalnızca function anahtar kelimesiyle bildirilmiş bir bileşende bulunur. Ok fonksiyonunun kendine ait bir this'i yoktur, bu yüzden this.head ataması yapamaz; ya bir fonksiyon bildirimi kullanın ya da head etiketlerini bırakıp bileşeni ok fonksiyonu olarak tutun. Düzgün bir ok bileşeni, doğrudan bir rota içinde kullanıldığında CaratsComponent olarak, düz bir fonksiyon ifadesi için anotasyon gerektiğinde ise CaratsComponentWithThis olarak tiplenir.
`CaratsComponent` tipi içe aktarılmalıdır; `@carats/render` tarafından dışa aktarılır. `this` parametresi yalnızca bir tip anotasyonudur ve derleme zamanında silinir.
HTML Öznitelikleri
HTML öznitelikleri olduğu gibi korunur ve dize olarak ele alınır. React'in aksine onclick veya onsubmit gibi bir olay özniteliğine fonksiyon geçiremezsiniz; bunun yerine bir afterMount geri çağrısının içinde addEventListener kullanın. React kodunu taşırken en sık karşılaşılan tek fark budur.
Yanlış (çalışmaz)
<button onclick={() => handleClick()}>Click me</button>
Fonksiyon geçerli bir HTML öznitelik değeri değildir; bu yüzden işaretlemeye çöp olarak girer ve hiçbir şey çağrılmaz.
Doğru
import { afterMount } from '@carats/hooks';
export default function MyButton() {
let handler: (() => void) | undefined;
afterMount(() => {
const button = document.getElementById('my-button');
handler = () => console.log('Clicked!');
button?.addEventListener('click', handler);
return () => button?.removeEventListener('click', handler!);
});
return <button id="my-button">Click me</button>;
}
Aynı kural `onsubmit`, `oninput`, `onchange` ve diğer tüm olay öznitelikleri için de geçerlidir. Öğeye bir `id` verin ve bir hook geri çağrısının içinde bulun.
Burnished Bileşenler
Burnished bileşenler verilerini culet'lerinden otomatik olarak çeker. Bu özelliği etkinleştirmek için bileşeninizi @carats/render'dan Burnish fonksiyonuyla sarın. Sarmalayıcı, bileşenin rotasını aynı rotadaki bir culet ile eşleştirir; bu yüzden ikisi de birebir aynı rota dizesi altında kayıt edilmelidir.
this bağlamıyla
import { Burnish } from '@carats/render';
export default Burnish<User>(function (user) {
this.head = <title>{user.name}</title>;
return <h1>Hello {user.name}</h1>;
});
recast seçeneğiyle
Framework bir rota için en son sunucu prop'larını önbelleğe alır. Önbelleğe alınmış değeri yeniden kullanmak yerine her işlemede yeniden çekmek için { recast: true } geçirin.
export default Burnish<User>((user) => <h1>Hello {user.name}</h1>, { recast: true });
Burnished bir bileşen diğer bileşenler gibi prop kabul etmeye devam eder; testlerin sunucu olmadan yazılabilmesinin nedeni budur.
İstemci Giriş Noktası
Giriş noktası facet'leri tarayıcıya bağlar ve ardından istemci tarafı işlemeyi başlatır. Uygulama içi yönlendirme açıkken clientRender() gereklidir ve mount'tan sonra çağrılmalıdır.
import { mount, clientRender } from '@carats/csr';
import facets from './facets.cara';
import './base.sass';
mount(facets);
clientRender();
Global stil dosyası bir sayfa yerine burada içe aktarılır, çünkü her sayfanın dayandığı tasarım token'larını ve temel sıfırlamaları içerir.
Vite Yapılandırması
İstemci Vite yapılandırması src/client üzerinden derler ve bir manifest ile dist/client dizinine çıktı verir; bu da sunucunun karmalı giriş dosyasına başvurmasını sağlar.
import { defineConfig } from 'vite'
import path from 'path'
export default defineConfig({
publicDir: path.resolve(import.meta.dirname, 'public'),
root: path.resolve(import.meta.dirname, 'src/client'),
base: '/',
appType: 'custom',
server: {
middlewareMode: true
},
build: {
outDir: path.resolve(import.meta.dirname, 'dist/client'),
emptyOutDir: true,
manifest: true,
minify: true,
rollupOptions: {
treeshake: true
}
}
})