Vanilla JSX örnekleri
JSX DOM öğeleri döndürürse?
ClickMe fonksiyonu bir düğme oluşturur ve tıklama sayısını gösterir
- Düğmeye her tıklandığında metin güncellenir
export default function ClickMe() {
let i = 0;
const el = Click me as HTMLButtonElement;
el.onclick = (e) => {
el.textContent = `Clicked ${++i} times`;
};
return el;
}
Yeniden kullanılabilirlik
ClickMe bileşeni birden çok kez kullanılarak her birinin farklı durumunu koruması sağlanabilir
import ClickMe from "./sample1.js";
export default () =>
;
Etkileşimli DOM ağacı oluşturma
TodoInput ve TodoList sınıfları kullanılarak yapılacaklar listesi yönetilebilir
- Öğeler eklenebilir ve tıklanarak kaldırılabilir
function TodoInput(attrs: { add: (v: string) => void }) {
const input = as HTMLInputElement;
input.placeholder = 'Add todo item...';
input.onkeydown = (e) => {
if (e.key === 'Enter') {
attrs.add(input.value);
input.value = '';
}
};
return input;
}
class TodoList {
ul = as HTMLUListElement;
add(v: string) {
const item =
- {v}
as HTMLLIElement;
item.onclick = () => item.remove();
this.ul.append(item);
}
}
export default () => {
const list = new TodoList();
list.add('foo');
list.add('bar');
return
list.add(v)} />
{list.ul}
;
};
Büyük veri işleme
FindNames fonksiyonu büyük miktarda veriyi işleyip filtreleyerek sonuçları gösterir
- Girilen değere göre eşleşen öğeler gerçek zamanlı olarak güncellenir
import { data } from "../fetch-dataset.js";
export default function FindNames() {
const status = as HTMLParagraphElement;
const results = as HTMLUListElement;
const input = as HTMLInputElement;
updateMatches();
function updateMatches() {
const matched = (data.entries().filter(([k]) => k.match(input.value)).toArray());
const matches = (Iterator.from(matched).map(match => ).take(30));
results.replaceChildren(...matches);
status.textContent = `${matched.length} / ${data.size}`;
}
return
{input}
{status}
{results}
;
}
function Item(attrs: { match: [string, number], regex: string }) {
const [name, count] = attrs.match;
const total = ({count});
return
-
{total}
;
}
function highlight(str: string, regex: string) {
if (!regex) return str;
const r = new RegExp(`(${regex})`, 'gi');
return str.replace(r, '$1');
}
imlib'e giriş
imlib, immaculatalibrary.com için geliştirilen bir kütüphanedir
- minigamemaker.com'u ve şu anda okumakta olduğunuz web sitesini oluşturmak için kullanılmıştır
- Mevcut durum yönetimi yeterli gelmediği için geliştirildi ve uygulama oluşturmanın en çok tercih edilen yoludur
GN⁺ özeti
- Bu yazı, JSX kullanarak DOM öğelerini doğrudan oluşturup etkileşime sokma yöntemini açıklıyor
- Geleneksel sanal DOM kullanmadan da büyük veriyi verimli şekilde işleme yaklaşımı sunuyor
imlib kütüphanesi, uygulama geliştirmeyi basit ve sezgisel bir hale getiriyor
- Benzer işlevlere sahip diğer projeler arasında React ve Vue.js bulunuyor
1 yorum
Hacker News yorumları
Gerçek DOM düğümleri döndürmek, JSX’in ve Lit gibi JSX olmayan kütüphanelerin büyük avantajı olan immediate mode tarzı API’yi ve
UI=f(state)modelini neredeyse etkisiz bırakırGerçek DOM değil, DOM’un bir tanımını döndürmek gerekir ki şablon yeni durumla tekrar tekrar değerlendirilebilsin ve bu şablonun render edildiği DOM verimli biçimde güncellenebilsin
Örnekler
input.onkeydown = ...veyathis.ul.append(item)gibi imperatif DOM API’leriyle güncelleme yapıyor; oysa bu tür kodlardan kaçınmak ve öğeler üzerinde şablon içinde dönmek, sanal DOMun başlıca faydası olabilirAncak sanal DOM’un sorunu diff hesaplamasının yavaş olması; bu da Lit’te olduğu gibi statik ve dinamik kısımları ayıran şablonlarla çözülebilir
Aksine, “büyük bir UI’yi istediğim gibi yeniden render etsem de sanal DOM halleder” diye düşündürerek ters etki yaratıyor; gerçek performans kötüleşirken uygulama yapısı da yeniden yazmadan düzeltilmesi zor olacak şekilde katılaşıyor
Dört ekipte aynı gidişatı gördüm; mimar olarak React’te yaşanacak sorunları gerekçe gösterip performansı gözeten vanilla bir yapı önermiştim, ama “kaçınmanın birçok yolu var” denerek kabul görmedi
Sonunda çoğu durumda insanların bunu bizzat zorlanarak öğrenmesi gerekiyor gibi
createElementfonksiyon çağrısı kalıbı için başka bir DSL’den ibarettir; anlattığınız faydalar framework ve runtime’dan gelirDaha kısa söylersek JSX, faydalı kullanım alanları olan alternatif bir fonksiyon çağrısı söz dizimidir
Eski şirketimde JSX’i test verisi factory’lerinde kullanıyorduk; XML gibi görünse de öğe oluşturma aşamasında builder pattern ile nihai veriye uygun bağlamsal kararlar alabiliyorduk
React ya da DOM ile ilgisi yoktu; bu, JSX olmadan deklaratif ifade edilemeyeceği anlamına da gelmiyordu
Şahsen DOM’u imperatif olarak güncellemeyi daha çok seviyorum. Ne olduğunu çok ince ayrıntısına kadar kontrol edebiliyor ve çok verimli yapılar tasarlayabiliyorum
Birinin katı metodolojisine göre düşünmek zorunda kalmadan uygulamaya özellik eklemeyi, değiştirmeyi, kaldırmayı ve düzeltmeyi kolaylaştırabiliyorum
UI=f(state)modelini zayıflattığına katılıyorum; ama bu, tüm bilişim alanındaki en sızdıran soyutlamalardan biri gibi hissettiriyorReact etrafında render’ı birden çok kez yapmamanın, gereksiz yenilemeleri engellemenin yollarına dair bir ekosistem oluşmasının bir nedeni var
Son 10 yılda statik site oluşturucularının durumundan bunaldığım için bu projeyi yaptım
Çoğunlukla statik web siteleri yaptığım için basit ve sezgisel araçlar istiyordum; JSX uygun görünüyordu, ama React gibi JSX framework’lerinin aşırı karmaşıklığından yorulmuştum
Bu yüzden JSX’i string’e render eden bir statik site oluşturucu yaptım; bunu tarayıcı tarafına genişletip JSX’i DOM öğelerine render ettirmek de doğal bir adımdı
Bazı durumlarda, özellikle layout’larda, paylaşılan component’ler için de iyi uyuyor. Genel olarak ortaya çıkan sonuçtan memnunum, ama bazı kısımlar epey hacky ve IDE desteği de daha iyi olabilir
Ayrıca bu yöntem SEO için de iyi uyuyor. Diğer JSX framework’lerinde düzgün çözüldüğünü hissetmediğim bir konuydu
Dokümantasyonda “SSG” yerine “static site generator” diye açık yazmak daha iyi olabilir. Statik site oluşturucu kullanmış olmama rağmen SSG’nin ne olduğunu bilmiyordum ve yapay zekaya sormak zorunda kaldım
Vue’dan gelmiş biri olarak şaşırdım; lit-html, yalnızca basit vanilla JS şablonlarıyla, event bağlama dahil Vue şablonlarının yaptığı birçok şeyi yapıyor
VSCode lit eklentisini kullanınca şablon içinde de syntax highlighting ve tam type checking alabiliyorsunuz
Marc Grabanski’nin Lit değil, vanillajs ile birlikte lit-html kullandığını tweet’lemesinden sonra öğrendim; kendim deneyince de çok iyi çalıştığını gördüm. Şu anda çözmeye çalıştığınız şeye oldukça benziyor
lit-htmlşablon paketini kullanırsanız şablon bölümünde anlatılanların çoğunu yapabilirsiniz: https://lit.dev/docs/templates/overview/lit-element’in component soyutlaması olmadan da mümkün: https://lit.dev/docs/libraries/standalone-templates/#renderi...Bu tür “ya öyle olsaydı”ların eğlenceli olmasının nedeni, JSX’in kökeninin Facebook’un XHP’sine kadar izlenebilmesi; XHP’nin de burada anlatılan kütüphaneye benzer görünüp davranan erken dönem JS standardı E4X’ten açıkça esinlenmiş olması
[1] https://engineering.fb.com/2010/02/09/developer-tools/xhp-a-...
[2] https://en.m.wikipedia.org/wiki/ECMAScript_for_XML
JSX’in E4X’in ötesine geçmesinin nedeni de buydu ve sonrasında JS içinde HTML şablonları için ciddi bir öneri çıkmadı
Yine de genel fikri modernleştirip yeniden canlandırmak mümkün gibi görünüyor: https://github.com/WICG/webcomponents/issues/1069
for eachyerinefor(of)girmesinin nedeni E4X’tirfor (:)elde edemememizin nedeni daha da saçma: Bazı TC39 üyeleri, bir gün dile sihirli biçimde geleceğine inandıkları:typeaçıklamalarıyla çakışabileceğini düşünüyorduJSX şablon ifadelerinin gerçek DOM düğümleri oluşturması fikriyle bir UI kütüphanesi yapmıştım
Model nesnelerini özelliklere bağlayarak emirsel event handler kalıp kodunun bir kısmını da ortadan kaldırıyor. Tahmin edileceği gibi, bunun iyi bir fikir olduğunu düşünüyorum
https://github.com/tomtheisen/mutraction
track({ clicks: 0 })ile bir model oluşturup tıklamadamodel.clicksdeğerini artıran ve bu değeri doğrudan DOM’a yansıtan kodlar yazılabiliyorBurada VanJS’den de bahsetmeye değer: https://vanjs.org/
Solid.JS gibi başka JSX kütüphaneleri de DOM düğümleri döndürüyor; bu fikrin ivme kazanması hoşuma gidiyor
Kullandığımız platforma ne kadar yakın olursak o kadar iyi olduğunu düşünüyorum. Soyutlama katmanları kimi zaman yararlı olabilir ama pratikte platformu gizlememiz gereken bir durumu hâlâ bulamadım
Facebook gibi devasa projeler bundan fayda görebilir, ama ben o ölçekte çalışmadım
Örnekler harika, ancak zamanla değişebilecek bileşen props’larını göstermemeleri önemli görünüyor
Böyle bir yetenek sanki hiç modellenmemiş. Buna ihtiyaç yoksa zekice bir yaklaşım, ama daha karmaşık uygulamalara nasıl ölçekleneceğini pek göremiyorum
Fark yalnızca, DOM öğelerini alışılagelmiş şekilde oluşturup ayarlayan 10 satırlık kodun daha özlü yazılması
Aslında bu framework’te gerçekten ilginç olan kısım bunun dışındaki neredeyse her şey. Statik site üreticisi tarafında JSX’in string döndürmesi, ham kaynak dizinini alıp SSG sırasında
string|Bufferüzerinde işlem yapılması,chokidarveswcüzerinde kurulmuş, kendi yazdığım son derece verimli ve hızlı modül sistemi gibi şeyler varJSX’i DOM olarak kullanma kısmı görsel olarak en dikkat çekeni, ama gerçekte daha çok bir gösteri numarası
Örneğin vanillajsx.com’un kaynak kodu çok özlü, açık ve kısa.
imlibdışında bağımlılığı olmadan bugün tek günde tamamını yazdım; JSX-as-DOM demosu en az yenilikçi bölüm: https://github.com/sdegutis/vanillajsx.com/tree/main/siteJSX’in somut DOM öğeleri döndürdüğü bu yaklaşımı seviyorsanız Solid tam olarak böyle çalışıyor ve buna düzgün bir reaktivite katmanı ekliyor
setTimeoutveyasetIntervalkullanımını nasıl engellediğini anlamıyorumYine de bu tür projelerin küçük kullanım senaryolarında iyi çalıştığı, fakat “gerçek dünya” senaryolarında çoğu zaman hızla dağıldığı konusunda hemfikirim
Uygulaması o kadar zor olmayabilir
Bu, Vanilla TSX’e çok benziyor: https://github.com/wisercoder/uibuilder
Vanilla TSX ile yazılmış bir uygulama örneği burada: https://github.com/wisercoder/eureka/tree/master/webapp/Clie...
Dilin çekirdeğinde XML bulunan ActionScript 3’ü hatırlatıyor
Yazması eğlenceli bir dildi ama ES4 olma konusunda malum şekilde başarısız oldu. Sonunda TypeScript ve JSX ile benzer bir noktaya varmamız 10 yıldan fazla sürmüş oldu
React’in ilk sürümünden 6 ay önce, Firefox 17’de web sayfaları için devre dışı bırakılmıştı
Son örneğin Firefox’ta çalışmadığı başka biri var mı merak ediyorum. Edge’de çalıştı ama Firefox’ta başarısız oldu
Uncaught (in promise) TypeError: Map.groupBy(...).entries().map is not a functionJSX’in aşağıdaki gibi yazmaktan neden daha çekici olduğunu pek anlayamıyorum
h("div", {}, [ h("p", {}, "this is easy"), ...list.map((l) => h("li", {}, l)) ])Böyle yapınca derleyici ve yeni söz dizimi oluşturmaya gerek kalmadan döngüleri ve değişken yerleştirmeyi vb. otomatik olarak elde ediyorsunuz. Biri açıklarsa sevinirim
Adil olmak gerekirse JSX’te de normal döngüler ve yerleştirme aynen kullanılıyor.
{}vanilla JS ifadeleri alıyorSadece öğe etiketlerini
createElementçağrılarına açan bir derleme adımı gerekiyorHerkes bilgiyi farklı işliyor olabilir ama o örnekte noktalama işaretleri çok fazla olduğu için hızlıca kavramak çok zor
Söz dizimini zihninde bizzat ayrıştırmadan oluşacak DOM yapısı görünmüyor; derleyici gerekip gerekmediğinden çok DOM yapısını bir bakışta anlamak çok daha önemli
Not olarak, nöroçeşitlilik sahibi biriyim ve umarım bu açıklama yardımcı olur
Tarayıcı geliştirici araçlarında gördüğüne benzediği için karşılaştırması ve hata ayıklaması kolay
Ama karmaşık bir uygulamada bileşen sayısı yüzlere çıkıp birbirlerini içe aktarıp kullanmaya başladığında, JSX etiketleriyle yazma biçimi sade ve anlaşılır bir söz dizimi gibi geliyor
React’e yönelik tepkinin önemli bir kısmı da sonuçta basit işler için aşırı kaçmasından kaynaklanıyor; gerçekten de aşırı
Ama herkesin yaptığı uygulama, karmaşıklık ve ihtiyaçlar farklı olduğundan, bir tarafın daha çekici olduğunu basitleştirerek söyleyemeyiz. Farklı problemler için farklı araçlar bunlar