jQuery selektori, optimizacija

Pozdrav,

dali je potrebno razmišljati o optimiziranju jQuery selectora?

Ukoliko recimo imamo selector $(parent).find('.className') …dali jQuery dolazi do elemenata sa className nekim direktnim putem, ili jQuery mora protrčati kroz sve elemente unutar parenta kako bi pronašao one koje odgovaraju upitu??

Ako je ova pretpostavka s “protrčavanjem” slučajno točna, onda vjerovatno postoje načini kako da se upiti optimiziranije zadaju??

U većini slučajeva nije potrebno razmišljati.
Ako je u pitanju masivan DOM s više od 10K node objekata onda ovo može biti bottleneck, ali u tom slučaju bi ja razmišljao kako da smanjim DOM, a ne optimizirao ovakve stvari. Ovo je relativno brzo u svim preglednicima. Ali zašto ne koristiš nativni DOM API koji je brži od jquery-va, na primjer querySelector ili querySelectorAll ?

1 Like

…nisam znao za querySelector, hvala ti na tom! Baš ću se poigrati sa razlikama u performansama.

Nego, konkretno ne pitam za optimizaciju iz razloga 10k node objekata…a opet osjetim na jednom mjestu delay zbog jQuery selectora.

Opisat ću baš kako radim jednu stvar, pa netko može možda preporučiti bolji pristup istom.

Znači, želja je napraviti neku klasu koja će nam štampati nekakvo HTML polje sa pripadajućim vrijednostima.
Za primjer, neka to HTML polje bude nekakav user-komentar…koji se sastoji od avatara, datuma komentara, teksta komentara, gumbića za ocjenjivanje komentara…gumbića “reply” …itd, svašta nešta može biti unutar jednog komentara.
No, očito se taj komentar-blok može pojaviti posvuda na stranici …i valja ga nekako generirati.

Sad ja to radim tako da napravim instancu toga komentara unutar jednog html file-a (tj. php file-a) …kojeg includam u nekakvo hidden polje u sam body.
Kad trebam generirati negdje taj komentar blok…onda proces započnem tako da kloniram tu instancu iz hidden polja, zatim sa jQuery selectorima dohvatim sve bitne elemente komentara iz te klonirane instance…dodjelim im dalje potrebna svojstva…vrijednosti…

Znači, nakon kloniranja znam dosta toga dohvaćati sa jQuery selectorima, i još se to multiplicira sa brojem komentara koji se generiraju…i tu se stvara ipak određena težina.

Eto, volio bi čuti druge pristupe rješavanju ovoga.

Nije jednostavnije sve generisati u hidden div i onda po potrebi samo prikazati taj hiden div?

Nije, jer to polje koje želimo generirati, u ovom primjeru user-komentar, se pojavljuje na više mjesta. Original je samo jedan…ali instanci originala može biti stotinjak na samo jednoj stranici.

Osim toga, svaka nova instanca originala ima različite vrijednosti (drugi user, drugi tekst, drugi datum…)…a osim različitih vrijednosti, često postoji potreba i za različitim varijacijama pojavljivanja.
Recimo komentar koji je vezan uz profil na profilnoj stranici može biti drugačija varijacija od komentara koji se veže uz neki članak…iako su im baze iste.

A suština je da kad radimo izmjene na bazi (originalu) …da se te izmjene preslikaju na sve instance koje nastaju iz originala.

Odlično, 12 puta je brži :slight_smile:

Koliko sam ja skuzio ti želiš generirat nekakav html blok na serveru i na klijentu, pogledaj što je React.js

Ako želiš napravit Load More onda nije. Load More radis da olaksas veličinu dokumenta i ubrzas ispis na ekranu.

Zato postoje templatei. Preporucam recimo underscore template. Definira se template (komentar blok), sa varijablama, i onda se tim varijablama pridruzuju vrijednosti u nekakvoj petlji. Poanta je da ce se DOM insertat jednom, nakon sta se svi templatei pripreme/popune, a ne element po element.

Malo opcenitije, prckanje po DOMu je sporo, a jQuery nije rjesenje za sve probleme.

Bacih pogled na underscore, no ima toga dosta…pa da skratim priču s pokojim pitanjem.
Uglavnom, ako sam dobro skužio…suština je ista kao kod mene. Prvo se definira template (ili kako sam ga ja nazvao gore “original”) …i s njim se štancaju instance.

E sad, očito postoji jedna bitna razlika jer spominješ ovo prckanje po DOMu kod mene. Možeš li mi pojasniti kako je to tamo izbjegnuto…tj. u kojem “formatu” postoji template i u kojem formatu postoje instance templatea prije nego se umetnu u DOM?

Koji trenutak je početak prčkanja po DOMu? Jeli to moment:

var element=document.createElement('div');

ili:

boxElement.appendChild(element);

…ili pak nešto treće?

Mislim da sam nešto skapirao…
Jedan od problema bi bio (možda i glavni) … što ja radim posebno izmjenu vrijednosti atributa za svaki element unutar bloka na kojem nešto želim mjenjati.
Znači, ja napravim klone od templatea…pa onda trčim od elementa do elementa i koregiram ga prema svojim željama. Svaka ta korekcija bi bila prčkanje po DOMu, što je poželjno izbjeći??

Znači, drugi pristup bi bio da uzmem innerHTML od templatea…unutar innerHTMLa trčim od željene pozicije do željene pozicije (što predstavljaju unaprijed naznačene varijable) …i mijenjam samo vrijednosti tih varijabli. Tako onda radim korekcije samo na stringu …a kad završim sa korekcijama, onda cijeli taj string (novi innerHTML) puknem u DOM, i tako imam samo jednu interakciju sa DOM-om??

Jel se o tome radi??

Appendanje je primjer “prckanja”. Odnosno sve sto zahtijeva od browsera ponovno renderanje. jQuery selectori dodaju na sporosti, ovisno o strukturi, a koristenjem templatea se ne treba pretrazivat node tree za svaki element.

Poanta je da se templatei spreme u varijablu, a onda se cijeli pripremljeni html (sa N iteracija templatea popunjenim zeljenim varijablama) zalijepi nazad u DOM. Sa appendChild, innerHTML, ili cim vec volis/trebas.
Prvi hit na googleu je ok: http://stackoverflow.com/questions/4778881/how-to-use-underscore-js-as-a-template-engine

Konkretno, cijeli set komentara ce bit jedan selektor (dom element u kojeg zelis zapisat rezultate), i jedan insert (svih komentara odjednom). Dok sam tipkao si napisao drugi post, i da, to je otprilike to, osim sto ne “trcis” od pozicije do pozicije nego underscore template to radi za tebe.

Shvatih to…opisao sam samo što se dešava, trčao ja…ili trčao underscore :wink:

Nego još nešto, kažeš da je problem sve što zahtjeva ponovno renderanje.
Što je onda sa situacijom, kad se ide ovom mojom trenutnom metodom, ali ako se uzme u obzir da se izmjene dešavaju dok je blok po kojem prčkamo u stanju display:none, ili ako još nije dodjeljen niti jednom parentu. To pitam, jer očito u tim situacijama ne postoje zahtjevi za renderiranje? …kad se na sceni ništa ne mijenja.

Dali u tom slučaju težinu procesa najviše uzrokuju dohvaćanja pretraživanjem node stabla?
No pored toga gornjeg…dali izmjena atributa nekog elementa (koja neće utjecati na rendering) …je bitno drugačija od izmjene stringa, koju imamo u verziji sa editiranjem innerHTML-a ??

Kasno je a imam posla, ali kratko - to sto je div hidden ne znaci nista. Browser i dalje reloada cijelo stablo na svaku izmjenu DOMa (DOM se mijenja vidio ti to ili ne), samo ne applya css na skriveni div. Jednostavno, ako radis izmjene po DOMu, triggeras reloadanje browseru. Dok izmjene drzis u varijabli, javascript je brz.

2 Likeova

Neznam dali sam što propustio vidjeti, ali mi nekako falilo opcija u ovom gore enginu, tako da sam nakraju išao složiti vlastiti engine prema željenim značajkama.
Složio sam si pravila prema kojima mogu:
-definirati ID-ove koji će se automatski generirati, te nakon “aktivacije” templatea, moguće je sve elemente dohvaćati putem objekata na kojeg se apliciraju elementi pozivom: template_instance.applyDom(objekt)
-definirati varijable
-definirati varijable sa defaultnom vrijednošću
-definirati varijable koje će biti prebrisane/ignorirane u destkop ili mobile verziji
-definirati varijable nad kojima će biti odrađen HTML escape.

Uglavnom, cool stvarčica…em radi brže, em je sad jednostavnije dohvaćati elemente (sve se desi zapravo automatski) …pa nema više selectora. Nema više konfuzije ako zamjenim nešto u HTMLu, da ću promjenom klase ili strukture HTMLa napraviti zbrku među selektorima :smiley:

I ono što mi je buety kod vlastitih alatića…da ih je uvijek lakše nadograđivati prema daljnjim željama/potrebama.

Sintaksa je sljedeća:

var template_instance= new template(string,param)

-string je string templatea, recimo:

<div id='$#element' class='whiteBox boxInfo $css'>
	<i id='$#btn.close' class='close'></i>
	<span>$span_value:defaultna vrijednost moze ici ovdje##</span>
	<span>$varijabla;je prekinuta sa točka zarez</span>
</div>

SINTAKSA:
Generiranje ID-ova:
$#element -> stvara id: element_uid_1 , dohvatljiv kao objekt.element
$#btn.element-> stvara id: btn.element_uid_1, dohvatljiv kao objekt.btn.element;
$#R -> vraća vrijednost zadnjeg generiranog ID-a, korisno za povezivanje checkboxa sa njihovim label.for atributom.

Generiranje varijabli:
$varijableName -> zamjenjuje sa varijablom koja se prosljeđuje unutar param objekta kod kreiranja templatea
ako varijabla nije prosljeđena, ništa se ne dešava.
$varijableName:miki## ->ako varijabla nije prosljeđena, miki je defaultna vrijednost
$+varijableName -> radi escapeHTML nad umetnutim stringom.
$(m)varijableName ->radi samo u mobilnoj verziji, inace vraca prazan string
$(d)vradijableName ->radi samo u destkop verziji, inace vraca prazan string
$pero;zdero ->točka zarez po potrebi razdvaja varijablu od okoline. Prirodna okolina koja razdvaja varijablu je: [<,>, ,’,",(,),$]

METODE:
template_instance.toNode() -> vraća HTML element izgrađen iz templatea;
template_instance.applyDom(objekt) -da bi se varijable(ID-ovi) prenjele na neki objekat, treba pozvati temlape_instance.applyDom(objekat) -> ovo se može pozvati tek nakon što se template ugradi u DOM, kako bi ID-ovi postali važeći.