Linux E X P R E S

Facebook

jQuery (3) – selektory v praxi

jquery.png

Po minulém stručném úvodu do selektorů se na ně podíváme trochu podrobněji. Jejich správné použití je důležité pro spolehlivost a rychlý běh.


Není selektor jako selektor

Selektory jsou velmi silný nástroj pro výběr objektů v objektovém modelu (DOM). Významnou pomocnou ruku poskytuje přímo webový prohlížeč, konkrétně nativní javascriptová metoda querySelectorAll() volaná na rodičovském objektu. Touto metodou lze vyselektovat objekty v míře, kterou daný prohlížeč podporuje, a to velmi rychle.

Ovšem jednak ne každý prohlížeč nabízí stejnou podporu (míra podpory specifikací CSS je v různých prohlížečích a jejich verzích poněkud odlišná), navíc některé užitečné selektory nejsou aktuálně k dispozici nikde.

Selektory nepodporované metodou querySelectorAll() řeší jQuery vlastní implementací (rozšířením), takže z pohledu aplikace všechno funguje, jak má. Ale rozdíl ve výkonu je značný. Je proto dobré se před použitím nějakého méně obvyklého selektoru přesvědčit, jak s ním bude jQuery v obvyklých případech nakládat.

Proto například nepoužívejte tyto selektory (v tomto i dalším příkladu budou uváděny vždy jako parametr konstruktoru jQuery, případně jako parametr metody volané na instanci):

$(':button')
$(':header')
$(':image')
$(':root')

Místo toho můžete použít následující, mnohem rychlejší ekvivalenty:

$('button, input[type="button"]')
$('h1, h2, h3, h4, h5, h6')
$('[type="image"]')
$('html')

První selektor vybírá tlačítko (element input nebo button), druhý nadpisy všech úrovní, třetí elementy typu „image“ (typicky to budou elementy input). Čtvrtý vybírá kořenový objekt celého dokumentu, což je v HTML vždy element html.

Některé selektory implementované v jQuery nemají svůj nativní ekvivalent. Pak je žádoucí provést „předfiltraci“, tedy použít například filtraci podle elementu. Jinak totiž selekce funguje tak, že se procházejí úplně všechny objekty (selektor '*') a u každého se rozhoduje, zda vyhovuje definovaným podmínkám. Opět pár příkladů zbytečně pomalých selektorů:

$('tr :even')
$(':animated')

A jejich vylepšené, rychlejší verze:

$('tr td:even')
$('div:animated')

U prvního případu je cílem použít selektor pro výběr sudých buněk tabulky. Selektor nejenže je pomalý, ale navíc spoléhá na to, že potomkem řádku tabulky (tr) bude vždy buňka tabulky (td). To ale není pravda, protože se používá také buňka záhlaví tabulky (th).

Druhý příklad tak trochu předbíhá o hodně dílů seriálu vpřed, až do jQuery UI. Proto prosím nyní nepřemýšlejte o tom, co ten animovaný objekt znamená. Budou se animovat jen a pouze elementy div, proto lze využít uvedený předvýběr. Celé to lze ještě dále urychlit, ale k tomu se vrátíme až za chvíli.



Dobrá praxe při používání selektorů

Pryč s univerzálním selektorem

Univerzální selektor ('*') je doslova žroutem výkonu. Znamená procházet celý strom DOM a pracovat se všemi objekty. Tento selektor se objevuje implicitně i tam, kde se použije nějaká pseudotřída. Málokdy je potřeba tento selektor použít – spíše by se dalo říct, že pokud k němu vše směřuje, je někde chyba.

Používejte identifikátory

Ve všech případech, kdy potřebujete vyselektovat jeden konkrétní objekt, je tou správnou cestou jeho identifikátor. Tedy například v HTML bude:

<img src="images/logo.png" alt="Logo" class="page-image" id="logo-image">

Potom se tento obrázek vyselektuje nejlépe takto:

$('#logo-image')

Identifikátor by měl být v rámci dokumentu vždy unikátní (požadavek specifikace HTML). Pokud není, je dokument „rozbitý“ a chování selektoru je pak nepředvídatelné.

Používejte dostatečně specifické selektory

Je lepší selektovat přímo jen ty objekty, kterých se operace týká. Nedostatečně specifické selektory mohou způsobit neočekávané chování, navíc mohou být pomalejší. Mějme třeba tyto dva příklady:

$('.external-link')
$('p a.external-link')

Cílem je udělat nějakou operaci s odkazem v textu, který patří do třídy „external-link“. Ta se sice aktuálně nikde nevyskytuje, ale v budoucnu se vyskytovat může. Podobně lze působnost selektoru omezit na odstavce, protože pokud by se nějaký odkaz dané třídy „zatoulal“ jinam, aplikovala by se operace i na něj, přestože to není cílem.

Nepřehánějte to se specifičností selektorů

Nic se nemá přehánět, platí to i u specifičnosti selektorů. Ve snaze dodržet v maximální míře předchozí doporučení, může vzniknout i něco jako:

$('form#mail input.mail-form')
$('#mail input')

Situace je však taková, že do třídy „mail-form“ patří všechny elementy input ve formuláři. Proto je uvedení třídy zbytečné. Ještě zbytečnější je uvedení elementu v kombinaci s identifikátorem, protože zcela vyhovuje samotný identifikátor a elementem se to nijak nevylepší.

Pozor však na situaci, kdy chceme vybrat sice podle identifikátoru, ale jen v případě, že objekt splňuje nějaké podmínky (což může být třída, pseudotřída, případně i element). Pak je samozřejmě kombinace identifikátoru a další podmínky zcela na místě.

$('#mail div input')

Toto je další ukázka zbytečně specifického selektoru. Většinou nemá žádný smysl přidávat do selektoru další úrovně (pokud se v DOM nacházejí), jen to zbytečně zpomaluje selekci a může to být zdrojem problémů při případných pozdějších změnách struktury.

Využijte metody

Tohle je opět trochu předběhnutí v seriálu. Instance jQuery mohou volat různé selekční metody, které vykonají stejnou práci jako selektory (obecně toho ale umějí více), ovšem často rychleji. Můžeme mít například selektory:

$('#mail input')
$('#mail > input')
$('#mail:parent')

Ty lze přepsat do následující podoby:

$('#mail').find('input')
$('#mail').children()
$('#mail').parent()

Metoda find() hledá v celém podstromě, metoda children() vybírá jen přímé potomky, metoda parent() vybírá rodičovský objekt. Všechny tři mohou mít (tady je to konkrétně použito v prvním případě) jako argument další selektor, který se použije pro výběr.

V jQuery je celá řada dalších podobných užitečných metod, na které se také později podíváme. Jejich výhodou je nejen vyšší rychlost při správném použití, ale také větší flexibilita. Můžeme si totiž dovolit udělat něco jako toto:

var form = $('#mail');
var txt = form.find('input[type="text"]');
var subm = form.find('input[type="submit"]');

Je snad už na pohled zřejmé, jaké výhody zde přináší použití metod oproti tomu, aby se pokaždé používal kompletní selektor. První řádek vyselektuje objekt formuláře, další řádky už pak hledají v podstromě pod formulářem. Pokud se například změní identifikátor formuláře, stačí ho změnit na jednom místě, není už potřeba sahat jinam. Současně je taková selekce rychlejší.

$('li:odd')
$('li').filter(':odd')

Závěrečný příklad ukazuje rozseknutí selektoru na dvě části. Nová je tu metoda filter(), která filtruje pomocí dalšího selektoru. Výsledek je stejný, jako kdyby se použil kompletní selektor, ovšem podobně jako u výše uvedeného použití metody parent() je to rychlejší.

Pohyb ve stromě DOM pomocí jQuery

Poslední úsek článku, který už trochu „naťukl“ některé metody, je v podstatě úvodem pro článek příští. Často se totiž potřebujeme různě pohybovat po stromě DOM a pracovat s jednotlivými objekty či jejich skupinami. Na to má jQuery jak již uvedené metody, tak i řadu dalších a podrobněji se na to podíváme příště.

Diskuze (0) Nahoru