Ich habe oft gehört, dass die Verwendung von JavaScript-Ereignissen, beispielsweise onClick()
in HTML, eine schlechte Praxis ist, da sie für die Semantik nicht gut ist. Ich möchte wissen, was die Nachteile sind und wie man den folgenden Code behebt.
<a href="#" onclick="popup('/map/', 300, 300, 'map'); return false;">link</a>
javascript
html
NiLL
quelle
quelle
#
, wird jeder, der Javascript deaktiviert hat, stecken bleiben und nichts tun können. Für einige Websites ist das eine gute Sache, aber zum einfachen Öffnen eines Fensters ist es absolut dumm, keinen "echten" Link bereitzustellen.<button>
, da Links auf eine tatsächliche Ressource verweisen sollen. Auf diese Weise ist es semantischer und für Benutzer von Bildschirmleseprogrammen klarer.Antworten:
Sie sprechen wahrscheinlich von unauffälligem Javascript , das so aussehen würde:
mit der Logik in einer zentralen Javascript-Datei, die ungefähr so aussieht:
Die Vorteile sind
quelle
onClick
. Sie können auch Unit-Tests schreiben, wenn Sie dies gegen Ihre Skripte tun möchten, was ebenfalls sehr schwierig ist. Ich würde annehmen, wenn sich der Code in einem befindetonClick
und keine Logik getrennt ist. Ich persönlich habe kein Problem damit, unauffälliges JavaScript zu debuggen, und die Vorteile beim Verwalten und Testen von JavaScript-Code sind viel zu groß, um ihn nicht zu verwenden.onclick
können kausale Zusammenhänge zwischen der Elementinteraktion und dem Effekt (Funktionsaufruf) expliziter abbilden und die kognitive Belastung verringern. Viele Lektionen werfen die Lernenden in das,addEventListener
was viel mehr Ideen in eine schwierigere Syntax packt. Darüber hinaus verwenden neuere komponentenbasierte Frameworks wie Riot und React dasonclick
Attribut und ändern die Vorstellung davon, was Trennung sein sollte. Das Übertragen von HTMLonclick
auf eine Komponente, die dies unterstützt, ist möglicherweise ein effektiverer "Schritt" -Prozess zum Lernen.Wenn Sie jQuery verwenden, dann:
HTML:
JS:
Dies hat den Vorteil, dass Sie weiterhin ohne JS arbeiten oder wenn die Benutzermitte auf den Link klickt.
Es bedeutet auch, dass ich generische Popups verarbeiten könnte, indem ich sie erneut umschreibe in:
HTML:
JS:
Auf diese Weise können Sie jedem Link ein Popup hinzufügen, indem Sie ihm einfach die Popup-Klasse geben.
Diese Idee könnte noch weiter erweitert werden:
HTML:
JS:
Ich kann jetzt das gleiche Stück Code für viele Popups auf meiner gesamten Site verwenden, ohne viele Onclick-Inhalte schreiben zu müssen! Ja für die Wiederverwendbarkeit!
Es bedeutet auch, dass ich Folgendes ändern kann, wenn ich später feststelle, dass Popups eine schlechte Praxis sind (was sie sind!) Und dass ich sie durch ein modales Fenster im Lightbox-Stil ersetzen möchte:
zu
und alle meine Popups auf meiner gesamten Website funktionieren jetzt völlig anders. Ich könnte sogar eine Feature-Erkennung durchführen, um zu entscheiden, was in einem Popup zu tun ist, oder die Präferenz eines Benutzers speichern, um sie zuzulassen oder nicht. Mit dem Inline-Onclick erfordert dies einen großen Aufwand beim Kopieren und Einfügen.
quelle
Bei sehr großen JavaScript-Anwendungen verwenden Programmierer eine stärkere Kapselung von Code, um eine Verschmutzung des globalen Bereichs zu vermeiden. Und um eine Funktion für die onClick-Aktion in einem HTML-Element verfügbar zu machen, muss sie sich im globalen Bereich befinden.
Möglicherweise haben Sie JS-Dateien gesehen, die so aussehen ...
Hierbei handelt es sich um sofort aufgerufene Funktionsausdrücke (IIFEs), und alle darin deklarierten Funktionen sind nur in ihrem internen Bereich vorhanden.
Wenn Sie
function doSomething(){}
innerhalb eines IIFE deklarieren und danndoSomething()
die onClick-Aktion eines Elements in Ihrer HTML-Seite ausführen, wird eine Fehlermeldung angezeigt.Wenn Sie andererseits einen eventListener für dieses Element in diesem IIFE erstellen und aufrufen,
doSomething()
wenn der Listener ein Klickereignis erkennt, sind Sie gut, weil der ListenerdoSomething()
den Bereich des IIFE teilt.Für kleine Web-Apps mit einer minimalen Menge an Code spielt dies keine Rolle. Wenn Sie jedoch große, wartbare Codebasen schreiben möchten,
onclick=""
sollten Sie daran arbeiten, dies zu vermeiden.quelle
Es ist aus mehreren Gründen nicht gut:
eval
Am einfachsten wäre es,
name
Ihrem<a>
Element ein Attribut hinzuzufügen , dann könnten Sie Folgendes tun:Obwohl die moderne Best Practice darin besteht,
id
anstelle eines Namens einen zu verwenden undaddEventListener()
statt zu verwendenonclick
, können Sie damit mehrere Funktionen an ein einzelnes Ereignis binden.quelle
addEventListener()
, und warum.Es gibt einige Gründe:
Ich finde, es hilft bei der Wartung, Markups zu trennen, dh die HTML- und clientseitigen Skripte. Mit jQuery ist es beispielsweise einfach, Ereignishandler programmgesteuert hinzuzufügen.
Das von Ihnen angegebene Beispiel ist in jedem Benutzeragenten fehlerhaft, der kein Javascript unterstützt oder dessen Javascript deaktiviert ist. Das Konzept der progressiven Verbesserung würde einen einfachen Hyperlink
/map/
für Benutzeragenten ohne Javascript fördern und dann programmgesteuert einen Klick-Handler für Benutzeragenten hinzufügen, die Javascript unterstützen.Beispielsweise:
Markup:
Javascript:
quelle
<a href="https://stackoverflow.com/map/" onclick="popup('/map/', 300, 300, 'map'); return false;">link</a>
Revision
Der unauffällige JavaScript- Ansatz war in der Vergangenheit gut - insbesondere die Bindung von Ereignishandlern in HTML wurde als schlechte Praxis angesehen (hauptsächlich, weil das,
onclick events run in the global scope and may cause unexpected error
was von YiddishNinja erwähnt wurde ).Jedoch...
Derzeit scheint dieser Ansatz etwas veraltet zu sein und muss aktualisiert werden. Wenn jemand ein professioneller Frontend-Entwickler sein und große und komplizierte Apps schreiben möchte, muss er Frameworks wie Angular, Vue.js usw. verwenden. Diese Frameworks verwenden jedoch normalerweise HTML-Vorlagen (oder erlauben die Verwendung), in denen Event-Handler gebunden sind direkt in HTML-Vorlagencode und dies ist sehr praktisch, klar und effektiv - zB in eckigen Vorlagen schreiben die Leute normalerweise:
In rohem js / html ist das Äquivalent dazu
Der Unterschied besteht darin, dass in raw js das
onclick
Ereignis im globalen Bereich ausgeführt wird - die Frameworks bieten jedoch eine Kapselung.Wo liegt also das Problem?
Das Problem ist, wenn unerfahrene Programmierer, die immer gehört haben, dass HTML-Onclick schlecht ist und die immer
btn.addEventListener("onclick", ... )
ein Framework mit Vorlagen verwenden möchten (addEventListener
auch Nachteile haben - wenn wir DOM auf dynamische Weise mit aktualisiereninnerHTML=
(was ziemlich schnell ist ) -, verlieren wir Ereignisse Handler binden auf diese Weise). Dann wird er mit schlechten Gewohnheiten oder einer falschen Herangehensweise an die Framework-Nutzung konfrontiert sein - und er wird das Framework auf sehr schlechte Weise verwenden -, weil er sich hauptsächlich auf den js-Teil und nicht auf den Template-Teil konzentriert (und unklare und schwer zu wartende Produkte produziert) Code). Um diese Gewohnheiten zu ändern, wird er viel Zeit verlieren (und wahrscheinlich wird er etwas Glück und Lehrer brauchen).Meiner Meinung nach, basierend auf den Erfahrungen mit meinen Schülern, wäre es für sie besser, wenn sie zu Beginn HTML-Handler-Bind verwenden. Wie ich bereits sagte, sind Handler zwar global aufgerufen, aber in dieser Phase erstellen die Schüler normalerweise kleine Anwendungen, die leicht zu steuern sind. Um größere Anwendungen zu schreiben, wählen sie einige Frameworks.
Was tun?
Wir können den unauffälligen JavaScript-Ansatz AKTUALISIEREN und Bindungsereignishandler (eventuell mit einfachen Parametern) in HTML zulassen (aber nur Bindungshandler - keine Logik wie bei einer OP-Abfrage in einen Klick setzen). Meiner Meinung nach sollte dies in rohem js / html erlaubt sein
oder
Code-Snippet anzeigen
Die folgenden Beispiele sollten jedoch NICHT zulässig sein
Die Realität ändert sich, sollte auch unser Standpunkt
quelle
addEventListener
. Anzeige 2. Ja, sie können überschrieben werden (aber normalerweise tut es niemand) - wo liegt das Problem? Anzeige 3. Handler wird nicht nach dem Löschen auf Klick Attribut hierEs ist ein
neuesParadigma namens " Unauffälliges JavaScript ". Der aktuelle "Webstandard" sieht vor, Funktionalität und Präsentation zu trennen.Es ist nicht wirklich eine "schlechte Praxis", es ist nur so, dass die meisten neuen Standards möchten, dass Sie Ereignis-Listener verwenden, anstatt JavaScript einzubinden.
Dies mag auch nur eine persönliche Sache sein, aber ich denke, es ist viel einfacher zu lesen, wenn Sie Ereignis-Listener verwenden, insbesondere wenn Sie mehr als eine JavaScript-Anweisung haben, die Sie ausführen möchten.
quelle
Ihre Frage wird wohl eine Diskussion auslösen. Die allgemeine Idee ist, dass es gut ist, Verhalten und Struktur zu trennen. Außerdem muss ein Inline-Klick-Handler afaik
eval
dazu gebracht werden, eine echte Javascript-Funktion zu werden. Und es ist ziemlich altmodisch, obwohl das ein ziemlich wackeliges Argument ist. Ah, nun, lesen Sie etwas darüber @ quirksmode.orgquelle
Leistung und Effizienz.
quelle
Zwei weitere Gründe, keine Inline-Handler zu verwenden:
Sie können langwierige Probleme erfordern
Eine gegebene beliebige Zeichenfolge, wenn Sie einen Inline - Handler in der Lage sein wollen , zu konstruieren , die eine Funktion mit dieser Zeichenfolge aufruft, für die allgemeine Lösung, werden Sie die entkommen müssen Attribut Trennzeichen (mit dem zugehörigen HTML - Entität), und du wirst müssen das Trennzeichen, das für die Zeichenfolge innerhalb des Attributs verwendet wird, wie folgt umgehen:
Das ist unglaublich hässlich. Wenn Sie im obigen Beispiel das
'
s nicht ersetzen würden, würde sich ein SyntaxError ergeben, daalert('foo'"bar')
die Syntax nicht gültig ist. Wenn Sie das"
s nicht ersetzen würden, würde der Browser es als Ende desonclick
Attributs (getrennt durch"
s oben) interpretieren , was ebenfalls falsch wäre.Wenn man gewöhnlich Inline-Handler verwendet, muss man sich daran erinnern, jedes Mal etwas Ähnliches wie das oben Gesagte zu tun (und es richtig zu machen ) , was auf einen Blick mühsam und schwer zu verstehen ist. Vermeiden Sie Inline-Handler besser vollständig, damit die beliebige Zeichenfolge in einem einfachen Abschluss verwendet werden kann:
Ist das nicht so viel schöner?
Die Scope-Kette eines Inline-Handlers ist äußerst eigenartig
Was glaubst du, wird der folgende Code protokollieren?
Probieren Sie es aus, führen Sie das Snippet aus. Es ist wahrscheinlich nicht das, was Sie erwartet hatten. Warum produziert es, was es tut? Weil Inline-Handler in
with
Blöcken ausgeführt werden. Der obige Code befindet sich in dreiwith
Blöcken: einer für dendocument
, einer für den<form>
und einer für den<button>
:Code-Snippet anzeigen
Da
disabled
es sich um eine Eigenschaft der Schaltfläche handelt,disabled
bezieht sich die Referenzierung im Inline-Handler auf die Eigenschaft der Schaltfläche und nicht auf die äußeredisabled
Variable. Dies ist ziemlich kontraintuitiv.with
hat viele Probleme: Es kann die Quelle verwirrender Fehler sein und den Code erheblich verlangsamen. Im strengen Modus ist das überhaupt nicht erlaubt. Aber mit Inline - Handler, sind Sie gezwungen , den Code durchlaufenwith
s - und das nicht nur durch einewith
, sondern durch mehr verschachteltenwith
s. Es ist verrückt.with
sollte niemals im Code verwendet werden. Da Inline-Handler implizitwith
ein verwirrendes Verhalten erfordern , sollten auch Inline-Handler vermieden werden.quelle