Was ist der Unterschied zwischen den verschiedenen Methoden zum Einfügen von JavaScript-Code in ein <a>?

86

Ich habe die folgenden Methoden zum Einfügen von JavaScript-Code in ein <a>Tag gesehen:

function DoSomething() { ... return false; }
  1. <a href="javascript:;" onClick="return DoSomething();">link</a>
  2. <a href="javascript:DoSomething();">link</a>
  3. <a href="javascript:void(0);" onClick="return DoSomething();">link</a>
  4. <a href="#" onClick="return DoSomething();">link</a>

Ich verstehe die Idee, eine gültige URL anstelle von nur JavaScript-Code einzufügen, nur für den Fall, dass der Benutzer kein JavaScript aktiviert hat. Für diese Diskussion muss ich jedoch davon ausgehen, dass JavaScript aktiviert ist (ohne JavaScript können sie sich nicht anmelden).

Ich persönlich mag Option 2, da Sie sehen können, was ausgeführt werden soll - besonders nützlich beim Debuggen, wenn Parameter an die Funktion übergeben werden. Ich habe es ziemlich oft benutzt und keine Browserprobleme gefunden.

Ich habe gelesen, dass die Leute 4 empfehlen, weil es dem Benutzer einen echten Link gibt, dem er folgen kann, aber wirklich, # ist nicht "echt". Es wird absolut nirgendwo hingehen.

Gibt es eine, die nicht unterstützt wird oder wirklich schlecht ist, wenn Sie wissen, dass der Benutzer JavaScript aktiviert hat?

Verwandte Frage: Href für JavaScript-Links: "#" oder "Javascript: void (0)"? .

Darryl Hein
quelle
Kleines Syntaxproblem: Wahl 2 sollte sein - <a href="javascript:DoSomething();"> Link </a> ohne die "Rückkehr"
DRosenfeld
Bitte ändern Sie die akzeptierte Antwort in @eyelidlessness Antwort. Ich denke, es ist der beste Ansatz, weil es um Semantik geht.
Michał Perłakowski

Antworten:

68

Ich mag Matt Kruses Javascript Best Practices-Artikel sehr . Darin erklärt er, dass die Verwendung des hrefAbschnitts zum Ausführen von JavaScript-Code eine schlechte Idee ist. Obwohl Sie angegeben haben, dass für Ihre Benutzer JavaScript aktiviert sein muss, gibt es keinen Grund, warum Sie keine einfache HTML-Seite haben können, auf die alle Ihre JavaScript-Links für ihren hrefAbschnitt verweisen können, falls jemand JavaScript nach dem Anmelden deaktiviert. Ich möchte Sie sehr ermutigen, diesen Fallback-Mechanismus weiterhin zuzulassen. So etwas wird sich an "Best Practices" halten und Ihr Ziel erreichen:

<a href="javascript_required.html" onclick="doSomething(); return false;">go</a>
Kuhgott
quelle
4
Wie wird der href-Wert dem Benutzer in der Statusleiste angezeigt? (die Leiste unten) Ich würde in Betracht ziehen, einen etwas benutzerfreundlicheren Link zu verwenden, z. "js.html? doSomething" Die Seite kann immer noch statisch sein. Auf diese Weise erkennt der Benutzer deutlich den Unterschied zwischen den Links.
Gene
6
Sie können diesen Wert mit dem title-Attribut überschreiben, z. B. <a href="javascript_required.html" title="Does Something" onclick="doSomething(); return false;"> go </a>
Conspicuous Compiler
Es sollte empfohlen werden, die Anforderungen auf der Seite javascript_required.html zu protokollieren und die Funktion zu protokollieren, die den Fehler verursacht hat.
Timo Huovinen
2
Haben Sie über die Konsequenzen für SEO nachgedacht?
DanielBlazquez
10

Warum sollten Sie dies tun, wenn Sie addEventListener/ verwenden können attachEvent? Wenn es kein hrefÄquivalent gibt, verwenden Sie kein <a>, verwenden Sie ein <button>und formatieren Sie es entsprechend.

Augenlidlosigkeit
quelle
9
Die Verwendung einer Schaltfläche anstelle eines Links ist in vielen Fällen nicht möglich.
Nickf
2
Weil es hässlich aussieht. Sie können neben dem Link ein Symbol hinzufügen. Es ist schwierig, sie in allen Browsern gleich zu formatieren. Und im Allgemeinen wechseln die Benutzer zu Links anstelle von Schaltflächen - sehen Sie sich den größten Teil des Stapelüberlaufs an.
Darryl Hein
2
Es sieht hässlich aus? Es sieht so aus, wie es sein soll. Tatsächlich denke ich, dass Schaltflächen tatsächlich mehr Stilflexibilität als Links haben, da sie inline sind, aber das Auffüllen von Browsern ordnungsgemäß übernehmen können. Alles, was mit einem Link gemacht werden kann, kann in Bezug auf CSS mit einer Schaltfläche gemacht werden.
Augenlidlosigkeit
2
Die Spanne kann nicht auf die Tastatur ausgerichtet werden.
Bobince
3
Und der Knopf ist (keuchend) semantisch korrekt. Span ist semantisch bedeutungslos. Eine Schaltfläche ist genau das , was der Autor semantisch verwenden möchte.
Augenlidlosigkeit
5

Sie haben eine andere Methode vergessen:

5: <a href="#" id="myLink">Link</a>

Mit dem JavaScript-Code:

document.getElementById('myLink').onclick = function() {
    // Do stuff.
};

Ich kann nicht kommentieren, welche der Optionen die beste Unterstützung bietet oder welche semantisch die beste ist, aber ich möchte nur sagen, dass ich diesen Stil sehr bevorzuge, da er Ihren Inhalt von Ihrem JavaScript-Code trennt. Es hält den gesamten JavaScript-Code zusammen, was viel einfacher zu pflegen ist (insbesondere wenn Sie dies auf viele Links anwenden), und Sie können ihn sogar in eine externe Datei einfügen, die dann gepackt werden kann, um die Dateigröße zu verringern und von Client-Browsern zwischengespeichert zu werden.

nickf
quelle
7
Wenn Sie 20 oder 30 verschiedene Links zu JS haben, kann dies ziemlich langweilig werden und zu viel JS führen.
Darryl Hein
Es ist nicht mühsamer, als durch HTML zu waten, um Javascript zu ändern. ... oder Sie könnten so etwas wie jQuery verwenden, das die Ereignisse für mehrere Elemente gleichzeitig leicht ändern kann ... $ ('# menu a'). click (function () {..})
nickf 30.10.08
1
@JKirchartz Ich sehe nicht, wie es predigt, wenn es Gründe für die Antwort gibt. Wenn Sie die Frage lesen, ist es wirklich ein "welche dieser 4 ist die beste", und ich habe nur darauf hingewiesen, dass es eine andere Option gibt, die er nicht in Betracht gezogen hat.
Nickf
Egal, Trololo, wenn man zwischen ABC und D wählt, wählt man nicht E.
JKirchartz
3
@JKirchartz Ja, ich glaube nicht, dass Sie dann wirklich den Zweck des Stapelüberlaufs haben. Wenn jemand fragt: "Was ist besser, um eine Web-App zu erstellen: Cobol oder Fortran?" Es ist akzeptabel, dieser Person zu sagen, dass sie nicht alle Möglichkeiten in Betracht gezogen hat. Die Frage lautet eindeutig nicht "welches von nur diesen vier Dingen das Beste ist".
Nickf
3
<a href="#" onClick="DoSomething(); return false;">link</a>

Ich werde das tun oder:

<a href="#" id = "Link">link</a>
(document.getElementById("Link")).onclick = function() {
    DoSomething();
    return false;
};

Kommt auf die Situation an. Für größere Apps ist die zweite am besten geeignet, da sie dann Ihren Ereigniscode konsolidiert.

Anik Islam Abhi
quelle
Wenn Sie 20 oder 30 verschiedene Links zu JS haben, kann dies ziemlich langweilig werden und zu viel JS führen.
Darryl Hein
und Fehler, die sich in Ihren Code einschleichen, können SEHR schwer zu debuggen sein. Diese Fehler treten sehr leicht auf, wie Ihr erstes Beispiel zeigt. :)
Nickf
1

Methode 2 hat einen Syntaxfehler in FF3 und IE7. Ich bevorzuge die Methoden Nr. 1 und Nr. 3, da Nr. 4 den URI mit '#' verschmutzt, obwohl dies weniger Typisierung verursacht ... Wie in anderen Antworten angegeben, ist die beste Lösung offensichtlich, HTML von der Ereignisbehandlung zu trennen.

Pier Luigi
quelle
Methode 2 von was? Die Fragen bleiben nicht in der Reihenfolge, in der SIE sie gesehen haben.
Diodeus - James MacFarlane
Methode 4 wird den URI nicht durcheinander bringen, wenn Sie dies sicherstellen return false. Aus diesem Grund ist Methode 4 wahrscheinlich die beste (von den aufgeführten).
Már Örlygsson
2
@Diodeus, ich glaube, Pier bezog sich auf die nummerierte Liste innerhalb der Frage , die tatsächlich vorhanden war, seit die Frage überhaupt veröffentlicht wurde.
Augenlidlosigkeit
1

Ein Unterschied, den ich zwischen diesen bemerkt habe:

<a class="actor" href="javascript:act1()">Click me</a>

und das:

<a class="actor" onclick="act1();">Click me</a>

ist das, wenn in beiden Fällen Sie haben:

<script>$('.actor').click(act2);</script>

dann wird für das erste Beispiel act2vorher ausgeführt act1und im zweiten Beispiel ist es umgekehrt.

JoelFan
quelle
1

Nur moderne Browser

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
(function(doc){
    var hasClass = function(el,className) {
        return (' ' + el.className + ' ').indexOf(' ' + className + ' ') > -1;
    }
    doc.addEventListener('click', function(e){
      if(hasClass(e.target, 'click-me')){
          e.preventDefault();
          doSomething.call(e.target, e);
      }
    });
})(document);

function doSomething(event){
  console.log(this); // this will be the clicked element
}
</script>
<!--... other head stuff ...-->
</head>
<body>

<!--buttons can be used outside of forms https://stackoverflow.com/a/14461672/175071 -->
<button class="click-me">Button 1</button>
<input class="click-me" type="button" value="Button 2">

</body>
</html>

Browserübergreifend

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
(function(doc){
    var cb_addEventListener = function(obj, evt, fnc) {
        // W3C model
        if (obj.addEventListener) {
            obj.addEventListener(evt, fnc, false);
            return true;
        } 
        // Microsoft model
        else if (obj.attachEvent) {
            return obj.attachEvent('on' + evt, fnc);
        }
        // Browser don't support W3C or MSFT model, go on with traditional
        else {
            evt = 'on'+evt;
            if(typeof obj[evt] === 'function'){
                // Object already has a function on traditional
                // Let's wrap it with our own function inside another function
                fnc = (function(f1,f2){
                    return function(){
                        f1.apply(this,arguments);
                        f2.apply(this,arguments);
                    }
                })(obj[evt], fnc);
            }
            obj[evt] = fnc;
            return true;
        }
        return false;
    };
    var hasClass = function(el,className) {
        return (' ' + el.className + ' ').indexOf(' ' + className + ' ') > -1;
    }

    cb_addEventListener(doc, 'click', function(e){
      if(hasClass(e.target, 'click-me')){
          e.preventDefault ? e.preventDefault() : e.returnValue = false;
          doSomething.call(e.target, e);
      }
    });
})(document);

function doSomething(event){
  console.log(this); // this will be the clicked element
}
</script>
<!--... other head stuff ...-->
</head>
<body>

<!--buttons can be used outside of forms https://stackoverflow.com/a/14461672/175071 -->
<button class="click-me">Button 1</button>
<input class="click-me" type="button" value="Button 2">

</body>
</html>

Sie können dies ausführen, bevor das Dokument fertig ist. Wenn Sie auf die Schaltflächen klicken, funktioniert dies, da das Ereignis an das Dokument angehängt wird.

Quellen:

Timo Huovinen
quelle