Přidat otázku mezi oblíbenéZasílat nové odpovědi e-mailem JS - Vytvoření třídy v událostech

Ahoj, můžu vytvořit třídu v nějaké události?
Třeba
<button onclick="new myClass()">Click me</button>

popřípadě pokud budu potřebovat objekt tak
<button onclick="obj = new myClass()">Click me</button>

Je to použitelné nebo je to prasárna? Díky

Předmět Autor Datum
Opět zaměňuješ třídu a objekt. Ale jinak to klidně možné je, jenom bych to nepsal přímo k elementu a…
Wikan 17.01.2020 14:33
Wikan
Děkuji za info.. Opět zaměňuješ třídu a objekt. Nerozumím, pokud vytvořím novou třídu var prom = n…
Kolemjdoucíí 17.01.2020 14:46
Kolemjdoucíí
pokud vytvořím novou třídu var prom = new myClass(); tak proměnná prom je objekt, ne? Ano, je to ob…
Wikan 17.01.2020 14:53
Wikan
Aha, v tom případě se asi nikdy nevytváří nová třída, vždy se vytváří nový objekt, ok. Jinak tohle…
Kolemjdoucíí 17.01.2020 15:07
Kolemjdoucíí
Požadavky na druhý parametr addEventListener: This must be an object implementing the EventListener…
Wikan 17.01.2020 15:17
Wikan
Při použití tohoto kódu s parametrem this <button onclick="new myClass(this)">Click me</button> vr…
Kolemjdoucíí 17.01.2020 15:29
Kolemjdoucíí
document.getElementById('button-1').addEventListener('click', (event) => new myClass(event.target));
Wikan 17.01.2020 15:38
Wikan
Prosím tě a tohle je co (event) ? Kam se to předává? Předpokládám, že tohle (event.target) najdu jak…
Kolemjdoucíí 17.01.2020 15:43
Kolemjdoucíí
Druhý parametr addEventListener je funkce, která jako první parametr přijímá událost (event), na kte…
Wikan 17.01.2020 15:47
Wikan
Tak zatím moc díky, jdu se tím prokousat. PS: ještě se zeptám, mají na sebe ty názvy nějakou vazbu?
Kolemjdoucíí 17.01.2020 19:18
Kolemjdoucíí
Jakou vazbu máš na mysli?
Wikan 18.01.2020 06:25
Wikan
Len upresním pár vecí: - myClass - myClass je trieda. V JavaScripte (a tiež vo väčšine iných jaykov…
moose 18.01.2020 00:57
moose
1,2 díky 3 proč ne var?
Kolemjdoucíí 18.01.2020 03:11
Kolemjdoucíí
Technicky nie je s "var" žiaden problém, ale "const" a "let" sú novšie konštrukty so zrozumiteľnejší…
moose 18.01.2020 03:31
moose
Když nastavím takto události, var polozky = document.querySelectorAll("#menu > li , #menu2 > li , #…
Kolemjdoucíí 18.01.2020 03:16
Kolemjdoucíí
Ak chceš odstrániť event listener, musíš vedieť jeho referenciu. V kóde, ktorý si skúsil, sa snažíš…
moose 18.01.2020 03:50
moose
const onClick = (event) => new MyClass(event.target)); Funguje to, dík. Tohle mi radil hned na začá…
Kolemjdoucíí 18.01.2020 12:27
Kolemjdoucíí
Jenže pokud to pověsím přímo na UL tak to kliknutí reaguje i na volné místa mezi LI. Toto sa ošetru…
moose 19.01.2020 22:48
moose
Chová se to nějak divně, pokud kliknu po prvé tak se v constructoru MyClass vypíše console.log('jsem…
Kolemjdoucíí 18.01.2020 14:13
Kolemjdoucíí
Ukaž kód.
Wikan 18.01.2020 14:45
Wikan
Tady je kód. Položky v seznamech se mění, vytvářejí se nové seznamy a některé seznamy se zase nezobr…
Kolemjdoucíí 18.01.2020 16:10
Kolemjdoucíí
const onClick = (event) => new MyClass(event.target); Tohle dej mimo funkci init. Jinak při každém…
Wikan 18.01.2020 16:27
Wikan
Díky a jinak je to správně? I to odstranění událostí které nebyly ještě nastavené?
Kolemjdoucíí 18.01.2020 16:42
Kolemjdoucíí
Pokud to dělá to, co si od toho představuješ, tak je to "správně". Ale já bych to teda dělal jinak.…
Wikan 18.01.2020 16:46
Wikan
Proč těm prvkům nepřiřazuješ listenery hned, jak je vytváříš? jak to myslíš, takto? <li id="m1" on…
Kolemjdoucíí 18.01.2020 17:42
Kolemjdoucíí
Ne. Pochopil jsem dobře, že ty elementy vytváříš pomocí JS? Pokud ano, tak jim při vytvoření rovnou…
Wikan 18.01.2020 17:48
Wikan
Pochopil jsem dobře, že ty elementy vytváříš pomocí JS? Ano, jenže některé vytvářím pouze jednou -…
Kolemjdoucíí 18.01.2020 17:55
Kolemjdoucíí
To je snad jedno kdy.
Wikan 18.01.2020 17:58
Wikan
No když nad tím přemýšlím, tak máš pravdu, ok, předělám to. Díky.
Kolemjdoucíí 18.01.2020 18:46
Kolemjdoucíí
Prosím tě a co se stane když budu používat opakovaně for (let element of elements) { element.addEv…
Kolemjdoucíí 19.01.2020 12:39
Kolemjdoucíí
Pokud to pořád bude ta samá instance onClick, tak nic.
Wikan 19.01.2020 12:58
Wikan
To volanie init v konštruktore máš asi navyše. Teraz vždy keď niekto klikne na LI, tak znovu všetko… poslední
moose 19.01.2020 22:53
moose

Děkuji za info..

Opět zaměňuješ třídu a objekt.

Nerozumím,
pokud vytvořím novou třídu
var prom = new myClass();
tak proměnná prom je objekt, ne?
Nebo myslíš něco jiného?

jenom bych to nepsal přímo k elementu ale do samostatné funkce.

Místo tohoto
<button onclick="new myClass()">Click me</button>

použít toto?
<button id="button-1"">Click me</button>
document.getElementById('button-1').addEventListener('click', new myClass);

pokud vytvořím novou třídu
var prom = new myClass();
tak proměnná prom je objekt, ne?

Ano, je to objekt. A proto je nesmysl psát, že vytváříš novou třídu. Vytváříš nový objekt.

A ne. Myslel jsem to takhle:

<button onclick="createObj()">Click me</button>
<script>
function createObj() {
    obj = new myClass();
}</script>

Aha, v tom případě se asi nikdy nevytváří nová třída, vždy se vytváří nový objekt, ok.

Jinak tohle ani nefunguje

<button id="button-1"">Click me</button>
document.getElementById('button-1').addEventListener('click', new myClass);

constructor v té třídě se automaticky spustí po načtení toho kódu ale na kliknutí tlačítka nereaguje.

Při použití tohoto kódu s parametrem this

<button onclick="new myClass(this)">Click me</button>

vrací v constructoru console.log(event) tohle

<button onclick="new myClass(this)">Click me</button>

a při použití tohoto kódu s parametrem this

<button id="button-1">Click me</button>'+
document.getElementById('button-1').addEventListener('click', () => new myClass(this) );

vrací v constructoru console.log(event) tohle

Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}

Co mám ještě prosím špatně? Děkuji

Len upresním pár vecí:

- myClass - myClass je trieda. V JavaScripte (a tiež vo väčšine iných jaykov) sa pre názov triedy používa PascalCase konvencia (a nie camelCase), t.j. v tomto prípade by bolo krajšie použiť MyClass.
- new myClass - Predpokladám, že toto si prečítal ako "nová myClass", t.j. "nová trieda". V skutočnosti je to "nový objekt triedy myClass". Tiež to môžeš prečítať ako "nová inštancia (triedy) myClass".
- v novom kóde by som "var" nepoužíval - jedine "const" alebo "let". "var" je dobré maximálne tak pri použití v konzole.

Technicky nie je s "var" žiaden problém, ale "const" a "let" sú novšie konštrukty so zrozumiteľnejším správaním.

JavaScript je jeden z najpopulárnejších jazykov, hlavne kvôli tomu že v prehliadačoch prakticky neexistuje rozumná alternatíva. Preto ho používa veľa vývojárov na rôznej úrovni od začiatočníkov po pokročilých. Veľa týchto vývojárov nepozná rozdiel medzi "var" (platnosť premennej sa viaže na funkciu) a "let" (platnosť premennej sa viaže na blok). V iných jazykoch je typické, že platnosť premennej sa viaže na blok a tak niektorí vývojári predpokladajú, že "var" sa správa rovnako. Z toho potom vznikajú chyby, ktoré by pri použití "let" nenastali. Použitie "const" robí kód čitateľnejším, pretože hneď vieš, že do danej premennej nebude priradená iná hodnota. Preto je v modernom kóde vo všeobecnosti odporúčané používať všade "const", a v prípade potreby "let".

Když nastavím takto události,

var polozky = document.querySelectorAll("#menu > li , #menu2 > li , #menu3 > li");
for ( var polozka of polozky){
polozka.addEventListener('click', (event) => new MyClass(event.target));
}

jak je zase všechny smažu? Zkoušel jsem tohle - bez výsledku :( Díky

var polozky = document.querySelectorAll("#menu > li , #menu2 > li , #menu3 > li");
for ( var polozka of polozky){
polozka.removeEventListener('click', (event) => new MyClass(event.target));
}

Ak chceš odstrániť event listener, musíš vedieť jeho referenciu. V kóde, ktorý si skúsil, sa snažíš odstrániť iný event listener, než ktorý bol pridaný (aj keď jeho implementácia vyzerá rovnako).

const onClick = (event) => new MyClass(event.target));
// alternatívne:
// function onClick(event) {
//     new MyClass(event.target);
// }

for (let polozka of polozky) {
    polozka.addEventListener('click', onClick);
}

for (let polozka of polozky) {
    polozka.removeEventListener('click', onClick);
}

Obyčajne je lepšie zavesiť obsluhu udalosti priamo na zoznam namiesto na jeho položky, hlavne v prípade, keď je tých položiek veľa (viď google: event delegation). Ja by som napr. dal všetkým tým menu rovnakú CSS triedu a cez addEventListener by som pridal obsluhu iba menu, nie každej položke menu (+ samozrejme upravil príslušnú obsluhu danej udalosti). Pravdepodobne si budeš chcieť ešte pozrieť, na čo sa používa event.currentTarget.

const onClick = (event) => new MyClass(event.target));

Funguje to, dík. Tohle mi radil hned na začátku Wikan, akorát jsem se k tomu ještě nedostal.

Obyčajne je lepšie zavesiť obsluhu udalosti priamo na zoznam namiesto na jeho položky, hlavne v prípade, keď je tých položiek veľa..

Jenže pokud to pověsím přímo na UL tak to kliknutí reaguje i na volné místa mezi LI.

Proč třeba nefunguje tohle?

document.body.removeEventListener('click', onClick);

Jenže pokud to pověsím přímo na UL tak to kliknutí reaguje i na volné místa mezi LI.

Toto sa ošetruje kontrolou v handleri. Ak chceš ošetriť iba kliknutie na LI, tak skontroluješ, že event.target.tagName === 'LI'. Ak máš v LI ešte ďalšie elementy, tak sa ti ale môže stať, že v target budeš mať napr. SPAN, alebo A, alebo iný element. Preto v takom handleri obyčajne chceš najprv získať LI element pomocou funkcie closest (pre podporu IE viď polyfill na danom odkaze). V tvojom konkrétnom prípade, ak by si to chcel robiť použitím event delegation a mať ekvivalentné s tvojim kódom, stačí skontrolovať, že event.currentTarget !== event.target (stále ti zostáva problém s elementami vnorenými v LI).

Chová se to nějak divně,
pokud kliknu po prvé tak se v constructoru MyClass vypíše console.log('jsem tu');
pokud kliknu po druhé tak se v constructoru MyClass vypíše console.log('jsem tu');
pokud kliknu po třetí tak se v constructoru MyClass vypíše 4 x console.log('jsem tu');
pokud kliknu po čtvrté tak se v constructoru MyClass vypíše 8 x console.log('jsem tu');
pokud kliknu po páté tak se v constructoru MyClass vypíše 16 x console.log('jsem tu');
pokud kliknu po šesté tak se v constructoru MyClass vypíše 32 x console.log('jsem tu');
atd...

pokud nastavím onclick každému LI ručně přímo v html, funguje to správně, nechápu.

Tady je kód. Položky v seznamech se mění, vytvářejí se nové seznamy a některé seznamy se zase nezobrazují vždy, proto je v konstruktoru třídy MyClass volání funkce init();

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <script>
      function init() {
        var elements;
        elements = document.querySelectorAll('#menu-1 > li, #menu-2 > li, #menu-3 > li');
        const onClick = ( event ) => new MyClass ( event . target ) ;
        for (let element of elements) {
          element.removeEventListener('click', onClick);
        } ;
        for (let element of elements) {
          element.addEventListener('click', onClick);
        } ;
      } ;
      class MyClass {
        constructor (event){
          console.log(event.id);
          init();
        } ;
      } ;
    </script>
  </head>
  <body onload="init()">
    <ul id="menu-1">
      <li id="m1">M1</li>
      <li id="m2">M2</li>
      <li id="m3">M3</li>
    </ul>
    <ul id="menu-2">
      <li id="mm1">MM1</li>
      <li id="mm2">MM2</li>
      <li id="mm3">MM3</li>
    </ul>
    <ul id="menu-3">
      <li id="mmm1">MMM1</li>
      <li id="mmm2">MMM2</li>
      <li id="mmm3">MMM3</li>
    </ul>
  </body>
</html>

Prosím tě a co se stane když budu používat opakovaně

        for (let element of elements) {
          element.addEventListener('click', onClick);
        } ;

a nebudu před tím spouštět

        for (let element of elements) {
          element.removeEventListener('click', onClick);
        } ;

Díky

Zpět do poradny Odpovědět na původní otázku Nahoru