- Cash, IE11+ modern tarayıcılarda DOM’u manipüle etmek için jQuery tarzı söz dizimi sunan, çok küçük bir jQuery alternatifi kütüphanesidir
- Modern tarayıcı özelliklerinden yararlanarak kod tabanını küçültür ve alışılmış zincirleme metotları çok daha küçük dosya boyutuyla kullanmayı sağlar
- jQuery ile %100 işlevsel eşdeğerlik hedeflemez, ancak günlük kullanım senaryolarının çoğunu kapsar ve uyguladığı API genel olarak jQuery ile uyumludur
- Boyutu minified & gzipped olarak 6KB’dır; jQuery Slim 3.4.1’in 24.4KB boyutuna kıyasla %76,6 daha küçüktür ve partial builds ile daha da azaltılabilir
- TypeScript kod tabanı, koddan üretilen TypeScript tipleri, ad alanlı olaylar ve tek tek metotların hariç tutulabildiği kısmi derlemeleri destekler
Cash’in çözdüğü sorun
- Cash, modern tarayıcılar için bir jQuery alternatifi olarak DOM manipülasyonu için jQuery tarzı
$() seçicisi ve zincirlenebilir koleksiyon metotları sunar
- Destek hedefi IE11+ tarayıcılardır
- Amaç jQuery’nin tüm özelliklerini birebir uygulamak değildir, ancak Cash’in uyguladığı özellikler çoğunlukla jQuery API’siyle uyumlu olacak şekilde tasarlanmıştır
- jQuery’den geçiş yapan kullanıcılar migration guide belgesini inceleyebilir
Boyut ve özellik karşılaştırması
- Dosya boyutu karşılaştırmasında Cash, Zepto 1.2.0 ve jQuery Slim 3.4.1’den daha küçüktür
- Unminified: 36.5KB
- Minified: 16KB
- Minified & Gzipped: 6KB
- jQuery Slim 3.4.1 minified & gzipped olarak 24.4KB’dır; Cash buna kıyasla %76,6 boyut tasarrufu sağlar
- Daha küçük bir bundle gerekiyorsa partial builds kullanılabilir
- Özellik karşılaştırmasına göre Cash modern tarayıcı desteği, aktif bakım, ad alanlı olaylar, TypeScript kod tabanı ve koddan üretilen TypeScript tipleri sunar
- Partial builds için Cash’te tek tek metotlar hariç tutulabilir; Zepto ve jQuery Slim’de ise tüm modüller düzeyinde hariç tutma olarak gösterilir
Kullanım
- Cash, jsDelivr üzerinden yüklenip tarayıcıda doğrudan kullanılabilir
<script src="https://cdn.jsdelivr.net/npm/cash-dom/…;
<script>
$(function () {
$('html').addClass ( 'dom-loaded' );
$('<footer>Appended with Cash</footer>').appendTo ( document.body );
});
</script>
npm install --save cash-dom
import $ from "cash-dom";
$(function () {
$('html').addClass ( 'dom-loaded' );
$('<footer>Appended with Cash</footer>').appendTo ( document.body );
});
API yapısı
$(), Cash’in temel seçici metodudur ve manipüle edilebilir düğüm koleksiyonları döndürür
- Bir fonksiyon geçirildiğinde DOM hazır olduğunda bu fonksiyonu çalıştırır
$() selector, DOM node, nodeList, HTML string, Cash collection ve document ready callback alabilir
- Cash genel olarak üç API sunar
- Sorgu seçicisi
- Koleksiyon metotları
- Global
$ nesnesinin kütüphane metotları
Koleksiyon metotları
- Koleksiyon metotları,
$() ile bir koleksiyon oluşturduktan sonra $(element).addClass(className) gibi çağrılır
- Sunulan kategoriler özellikler, koleksiyon, CSS, veri, boyutlar, efektler, olaylar, form, DOM manipülasyonu, offset ve gezinme olarak ayrılır
- Başlıca metotlar şunları içerir
- Sınıf/özellik:
addClass, removeClass, toggleClass, attr, prop, removeAttr
- Koleksiyon işleme:
add, each, eq, filter, first, get, map, slice
- DOM manipülasyonu:
append, prepend, before, after, html, text, clone, remove, replaceWith, wrap
- Olaylar:
on, off, one, ready, trigger
- Gezinme:
find, children, closest, parent, parents, siblings, next, prev
- Bazı extra methods sunulur, ancak varsayılan olarak devre dışıdır
$.fn, koleksiyonların ana prototipidir ve eklenti gibi tüm koleksiyonlara özel metotlar eklemeye olanak tanır
Global Cash metotları
- Global
$ nesnesi tip kontrolü ve yardımcı metotlar içerir
- Tip kontrol metotları
$.isArray, $.isFunction, $.isNumeric, $.isPlainObject, $.isWindow sunar
- Yardımcılar arasında
$.guid, $.each, $.extend, $.parseHTML, $.unique bulunur
$.extend, hedef nesneyi kaynak nesnenin özellikleriyle genişletir ve derin genişletmeyi de destekler
$.parseHTML, HTML string’inden bir koleksiyon döndürür; $.unique ise tekrarları kaldırılmış yeni bir dizi döndürür
Genişletme ve katkı
- Cash özel metotlarla genişletilebilir; genişletme yöntemi extending Cash belgesinde anlatılmıştır
- Sorunlar veya özellik istekleri GitHub’da issue olarak açılabilir
- Pull request iş akışı sırasıyla depoyu klonlama, bağımlılıkları kurma,
npm run dev ile otomatik yeniden derleme, npm run test ile testleri çalıştırma ve gerekirse README’yi güncellemedir
- Lisans MIT’dir
1 yorum
Hacker News yorumları
Günümüz tarayıcıları oldukça iyi hale geldiği için DOM manipülasyonunu basitleştirmek adına çoğu zaman aşağıdaki iki satırlık alias yeterli oluyor
dqs = document.querySelector.bind(document);dqsA = document.querySelectorAll.bind(document);Böylece
document.querySelector('#country')yerinedqs('#country'),document.querySelectorAll('.city')yerine dedqsA('.city')gibi kullanılabiliyorGeri kalanı için sadece yerel tarayıcı fonksiyonlarını kullanmak da sorun değil; genelde de
import { dqs, dqsA } from '/lib/js/dqs.js';gibi bir modülden içe aktarılıyorhttps://github.com/no-gravity/dqs.js
querySelector/querySelectorAlliçin bağlanmış bu iki satırın kendisi kullanışlı ve makul görünüyor, ama bunuimportile almak abartıSonuçta sadece iki basit satır; bağımlılık yapmaya gerek yok, kopyalayıp yapıştırmak yeterli
Örneğin birden fazla olayı ele alan
$.fn.one()veya$.fn.on()jQuery/Cash ile daha kolay kullanılıyor; iç implementasyona bakınca da epey iş olduğu görülüyor: https://github.com/fabiospampinato/cash/blob/master/src/even...querySelectorAll()live collection değildir; bu yüzden sıkça doğrudan diziye çevrilerek şöyle kullanılırdqsA = s => Array.from(document.querySelectorAll(s));Böylece sonuç üzerinde
.map()veya.filter()gibi dizi metotlarını doğrudan kullanabilir, jQuery’ye benzer bir his elde edersinizÖrneğin test sırasında Safari’de bir öğenin
selectolayı hiç tetiklenmedi, bazı tarayıcılarda ise yalnızca imleç konumu değiştiğinde olay oluşmadıComponent, state, props gibi React özelliklerine ihtiyaç olmasa bile yalnızca yerel tarayıcı fonksiyonları yeterli değildi; React DOM’un tarayıcı farklarını örtme değeri ortaya çıktı
Polyfill’lerin neredeyse tamamını kaldırdıktan sonra jQuery’nin geriye kalan kalıcı avantajının otomatik liste işleme olduğunu düşünüyorum
Bir formdaki tüm düğmelerin seçimini tek bir çağrıyla kaldırabilme yeteneğini başka yerde yakalamak hâlâ zor; üst öğe sorguları için de durum aynı
Ancak implementasyon açısından en büyük sorun, liste boş olduğunda sessizce başarısız olması
DOM ağacını sonradan yerleşim amaçlarıyla refactor ederken ortaya çıkan bu tür çok fazla hatayı düzelttiğim için, jQuery’yi bugün yeniden yapsaydım varsayılan olarak boş kümede hata verdirir, gerçekten umursamadığımda sessizce başarısız olması için zincir çağrı veya bayrak koyardım
Geçmişte Sizzle’ı çıkarıp bunu bu şekilde değiştirebilir miyim diye birkaç saat incelemiştim ama daha ileri gitmedim
Sonuçta jQuery, kütüphane mi framework mü şeklindeki eski tartışmayla da bağlantılı; dev framework’lerle uzun süre tek sayfa uygulamaları yaptıktan sonra yeniden bir hayal kırıklığı vadisine yaklaşıldığı hissi var
.fooöğelerinin hepsini gizle dendiğinde varsa gizlenir, yoksa hiçbir şey olmaz; CSS’e benzeyen bir fire and forget yaklaşımıdır.foo { color: red; }yazdığınızda belgede.fooolmasa bile küçük bir overhead dışında yan etki oluşmazdocument.querySelectorAll('input[type=checkbox]').forEach((i) => i.checked = false);Bu, üzerinde yineleme yapılabilen
NodeListve iterator yardımcılarından yararlanan bir yaklaşımBirçok üst öğe sorgusu
element.closest()ile halledilebilirjQuery tabanlı kodda tüm geliştiricilerin projedeki tüm seçicileri bilmesi ve DOM değiştiğinde bunları güncellemesi gerekir ki bu elbette imkânsız
jQuery başlatma fonksiyonunu kendi implementasyonunuzla değiştirip uzunluk kontrolünü zorunlu kılmak mümkün görünüyor
Ana akım web siteleri kelimenin tam anlamıyla megabaytlarca JavaScript dağıtırken, 50KB tasarruf etmek için daha az özellikli bir kütüphaneyi baştan yazmanın neden gerekli olduğunu anlamıyorum
Birçok yazı paket boyutu ve bant genişliği kısıtları nedeniyle jQuery kullanımına karşı çıkarken, aynı anda çok daha fazla bant genişliği kullanan SPA framework’lerini savunuyor
Tamamen saçma bir cargo cult akıl yürütmesi
Üç durumda da cevap aynı: büyük olan şey ben değilim, ben daha küçük başka bir şey yapıyorum
Bir diğer cevap da şu: sorun bir şeyin fazla büyük olmasıysa, daha küçük olmak çözüm gibi durur
Sonuçta asıl sormak istenen şey geliştiricinin neden bir kütüphaneyi yeniden yazmaya zaman harcadığı gibi görünüyor; ama bu o kadar şaşırtıcı değil
Programlamanın önemli bir kısmı zaten yapılmış şeyleri yeniden yapmakla geçer; iş gerektirdiği için, biraz farklı davranış veya performans özellikleri gerektiği için ya da sadece nasıl çalıştığını öğrenmek istendiği için yapılır
jQuery alternatifi arıyorsanız, jQuery 4.0’ı çok uzun süre bekledikten sonra sonunda bazı önemli farkları olan, kendi jQuery benzeri aracımı yaptım.
Animasyonlar, tween’ler ve timeline’lar için jQuery’nin özel sistemi yerine saf CSS kullanıyor; tekil öğeleri ve listeleri şeffaf biçimde ele alıyor ve inline kullanıma yöneliyor.
me()için 1 öğe döndürdüğü ya da ilk öğeyi veyanulldöndürdüğü yazıyor;any()içinse bir dizi veya boş dizi döndürdüğü belirtilmiş.Ama aşağıdaki örnekler
any('button')?.forEach(...),any('button')?.map(...)gibi kullanımlarlanullolabileceğini ima ediyor.any()üstteki açıklamadaki gibi her zaman dizi mi döndürüyor, yoksa alttaki örneklerdeki gibinullda mümkün mü, kafa karıştırıyor.Özellikle davranışın yerelliği ilgimi çekiyor.
currentScript.parentElementkullanma deneyiminizin nasıl olduğunu merak ediyorum.Geçen ay hızlıca araştırdığımda, muhtemelen uç durumlarda güvenilir olmadığı izlenimini edinmiştim; ama tam olarak hangi durum olduğunu hatırlamıyorum.
Derinlemesine incelemedim ve bunu düzgün çalışır hale getirmiş olmanıza sevindim.
asyncya damoduleolmadığı varsayımıyla, art arda 3 script yüklense bile tüm tarayıcılardacurrentScript.parentElementhâlâ çalışmalı değil mi diye düşünüyorum.SvelteKit de bu tartışmayı yaptı ve sonunda hedef öğeyi belirtmek için rastgele ID uyguladı: https://github.com/sveltejs/kit/issues/2221
Migrasyon rehberine bakarken jQuery’nin yapabildiği ama Cash’in yapamadığı özellikler arasında, bilmediğim ve bir gün kullanmaya değer olabilecek birkaç şey öğrendim.
https://github.com/fabiospampinato/cash/blob/master/docs/mig...
Genişletme hedefi olarak, TypeScript template string sihrini kullanıp öğe tipini doğru biçimde çıkarabilse iyi olurdu.
Örneğin
$('div#name')ifadesininHTMLDivElementolduğunu statik olarak çıkarabilir.typed-query-selector.Gerçek kullanım örneği burada: https://github.com/GoogleChrome/lighthouse/blob/main/types/i...
TypeScript’te bunun mümkün olup olmadığını bilmiyorum ve nasıl yapılabileceğini pek göremiyorum.
jQuery 4’ün modern tarayıcılar için bir jQuery alternatifi olduğunu duymuştum.
Geliştirdiğim tarayıcı uzantısında başta bunu kullandım, ama sonunda bir JSX kütüphanesine geçtim.
“Basit uygulama” alanının ötesine geçildiğinde jQuery çok hızlı şekilde akıl yürütmesi zor koda dönüşüyor; jQuery’den ilham alan bir kütüphaneyi bizzat yapmış biri olarak da böyle hissediyorum.
Sonuçta işe uygun aracı kullanmak gerekiyor.
[1]: https://github.com/aleclarson/dough
Orta-büyük ölçekli uygulamalarda jQuery’yi iyi idare edebiliyorsanız sorun yok, ama benim tercihim değil.
Eskiden JS’i azaltmaya çalışırken https://github.com/filamentgroup/shoestring kullanmıştım.
Ana nedeni, gerçekten ihtiyaç duyulan şeyleri ekleyen özel build sunmasıydı.
Cash’te de benzer bir özellik var gibi, ama dokümanlarda biraz daha saklı: https://github.com/fabiospampinato/cash/blob/master/docs/par...
Kullanacak olsam önce onu denemeyi düşünürdüm.
Yine de bugünlerde tarayıcıların sunduğu şeyleri doğrudan kullanmanın daha iyi bir tercih olduğunu hâlâ düşünüyorum.
Gerçekten oldukça iyi ve jQuery artık mutlaka gerekli değil.
Özellikle küçük bir jQuery alternatifi bile 6 kB iken, React benzeri bir kütüphane olan Preact’in bunun yarısı boyutunda olduğu düşünülürse bu daha da doğru.
Zaten var olan Web API’lerine takma ad vermekten öte ne kadar yardımcı olduğundan pek emin değilim.