Autor | Zpráva | ||
---|---|---|---|
hypot Profil |
#1 · Zasláno: 7. 8. 2017, 11:41:06
Zdravím,
chtěl jsem na odrolování ke kotvám využít tuto funkci, ale nechtěl jsem psát ke každému odkazu onclick, takže jsem HTML upravil takto <p class="kotvy">Nadpis 1</p> <p class="kotvy">Nadpis 2</p> (atd.) <h3 id="kotva-1">Nadpis 1</h3> <h3 id="kotva-2">Nadpis 2</h3> var kotvy = document.getElementsByClassName("kotvy"); for (var i=1; i<=kotvy.length; i++) { kotvy[i].addEventListener("click", function () { var kotva = document.getElementById("kotva-"+i).offsetTop; (atd.) Děkuji. |
||
weroro Profil |
#2 · Zasláno: 7. 8. 2017, 13:27:33
Skús toto:
Živá ukázka |
||
Dan Charousek Profil |
#3 · Zasláno: 8. 8. 2017, 18:23:39
hypot:
Můžeš ID cílového nadpisu uvést ve vlastním atributu na odkazu: Živá ukázka Což má výhodu v tom, že nezáleží na pořadí prvků. Nebo cesta, kterou jsi se chtěl vydat původně: Živá ukázka |
||
Časová prodleva: 5 dní
|
|||
hypot Profil |
#4 · Zasláno: 13. 8. 2017, 15:26:23
To poslední vypadá zajímavě, ale nerozumím syntaxi: nevím, k čemu se vztahuje na konci (i + 1) (a proč je to zapsáno takto), a nerozumím, proč je celá přechozí anonymní funkce v kulatých závorkách. A vlastně mi taky není jasné, jak se dosadí konkrétní hodnoty (kde se vezmou) za parametr index. Díky za vysvětlení.
|
||
Dan Charousek Profil |
#5 · Zasláno: 13. 8. 2017, 19:03:07
hypot:
Je to celkem jednoduché: for (var i = 0; i < kotvy.length; i++) { // ... } Tohle je jasné, iteruji nad kolekcí kotev. i jde od nuly a moje IDčka na kotvách jdou od 1 proto je tam to (i + 1) , ale o tom později.
Proč nefunguje for (var i = 0; i < kotvy.length; i++) { kotvy[i].addEventListener('click', function() { const nadpis = document.getElementById('kotva-' + i); console.log(nadpis.textContent); }); } které se zdá být správné? Na vině je rozsah viditelnosti proměnné i , která je definována v tom for cyklu (for (var i ...) .
Jde o to, že takový zápis je ekvivalentní zápisu: var i; for (i = 0; i < kotvy.length; i++) { kotvy[i].addEventListener('click', function() { const nadpis = document.getElementById('kotva-' + index); console.log(nadpis.textContent); }); } // proměnná i je definována i zde To znamená, že po skončení cyklu hodnota i je 3. Důležité je to, že když potom nastane click event tak selectuješ element právě podle tohohle i, které je 3 nehledě na to, na které tlačítko klikneš. Jak to lze řešit? Ve svém předchozím příspěvku jsem nastínil 2 řešení. To první je vcelku jasné, takže rozeberu to druhé a přidám třetí nejjednodušší řešení. Potřebuješ dosáhnout toho, aby každý callback toho eventu referencoval statickou proměnnou s pevně daným indexem. Proto potřebuješ zajistit, aby proměnná podle které vyhledáváš ty kotvy v document.getElementById nebyla závisla na té iterační proměnné i . Toho lze dosáhnout vytvořením nové scope pomocí funkce. Já jsem to napsal všechno najednou, takže proto ta anonymní funkce uzavřena do kulatých závorek a rovnou zavolána: (function(i) { console.log(i); })('Hello World!') - Okamžitě se zavolá a provede - vypíše se předaný parametr i no a já předávám 'Hello World', takže se vypíše hello world. Pokud bych to chtěl rozepsat, tak to můžu napsat takto:
// Toto je funkce, která nám vytvoří novou scope, která vrátí funkci, která se pak stane právě tím callbackem. Jde o to, že ta vnitrní funkce referencuje proměnnou index, která se už nijak nemění. function callbackFactory(index) { return function() { const nadpis = document.getElementById('kotva-' + index); console.log(nadpis.textContent); } } for (...) { kotvy[i].addEventListener('click',callbackFactory(i)); } Tohle je ekvivalentní té mé druhé ukázce. Jiné řešení umožňuje nové klíčové slovo let , které bylo představeno v ES6 (kompatibilita s prohlížeči), které celý problém řeší daleko elegantněji. let je podobné klasickému var, s tím že pokud se pomocí let deklaruje iterační proměnná for cyklu, tak je ta proměnná viditelná pouze uvnitř daného for cyklu, ale především, v každé iteraci ukazuje na jinou instanci, takže tam nedochází k problémům, jako s var. Jinými slovy. Tvé původní řešení bude funkční, pokud vyměníš var za let:
for (let i=1; i<=kotvy.length; i++) { kotvy[i].addEventListener("click", function () { var kotva = document.getElementById("kotva-"+i).offsetTop; (atd.) Toto už bude fungovat, tak jak má. Rozdílů mezi let a var je více, já jen zmínil ty, které jsou relevantní tomuto problému. |
||
Časová prodleva: 9 dní
|
|||
hypot Profil |
#6 · Zasláno: 22. 8. 2017, 09:44:27
Přinejmenším část problému jsem myslím pochopil, i když některé věci mi zůstávají nejasné. Dovolím si zeptat se na jednu věc k tomu. Na stránce Closures je příklad
function makeFunc() { var name = 'Mozilla'; function displayName() { alert(name); } return displayName; } var myFunc = makeFunc(); myFunc(); |
||
Dan Charousek Profil |
#7 · Zasláno: 22. 8. 2017, 10:06:17
hypot:
„Nevím, proč není možné přímo zavolat funkci makeFunc a proč je nutné ji nejprve vložit do proměnné myFunc.“ Je to trochu jinak než píšeš. funkci makeFunc je možné zavolat bez přiřazení do proměnné, ale všimni si, co ta funkce vrací. Vrací další funkci, která se uloží do proměnné myFunc a pak se zavolá myFunc() . Pokud bys to chtěl udělat vše najednou, tak by to bylo makeFunc()() .
|
||
Časová prodleva: 7 let
|
0