Jaka jest różnica między różnymi metodami umieszczania kodu JavaScript w <a>?

87

Widziałem następujące metody umieszczania kodu JavaScript w <a>tagu:

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>

Rozumiem ideę próby umieszczenia prawidłowego adresu URL zamiast samego kodu JavaScript, na wypadek gdyby użytkownik nie miał włączonej obsługi JavaScript. Ale na potrzeby tej dyskusji muszę założyć, że JavaScript jest włączony (nie mogą się bez niego zalogować).

Osobiście podoba mi się opcja 2, ponieważ pozwala zobaczyć, co zostanie uruchomione - szczególnie przydatne podczas debugowania, w którym parametry są przekazywane do funkcji. Używałem go dość często i nie znalazłem problemów z przeglądarką.

Czytałem, że ludzie polecają 4, ponieważ daje użytkownikowi prawdziwy link do naśladowania, ale tak naprawdę # nie jest „prawdziwy”. Nigdzie nie pójdzie.

Czy jest taki, który nie obsługuje lub jest naprawdę zły, kiedy wiesz, że użytkownik ma włączoną obsługę JavaScript?

Pytanie pokrewne: Href dla linków JavaScript: „#” czy „javascript: void (0)”? .

Darryl Hein
źródło
Mały problem ze składnią: wybór nr 2 powinien brzmieć - <a href="javascript:DoSomething();"> link </a> bez „zwrotu”
DRosenfeld,
Zmień zaakceptowaną odpowiedź na odpowiedź @eyelidlessness. Myślę, że to najlepsze podejście, ponieważ dba o semantykę.
Michał Perłakowski

Odpowiedzi:

69

Bardzo podoba mi się artykuł Matta Kruse poświęcony najlepszym praktykom w Javascript . Stwierdza w nim, że używanie hrefsekcji do wykonywania kodu JavaScript to zły pomysł. Mimo że powiedziałeś, że Twoi użytkownicy muszą mieć włączoną obsługę JavaScript, nie ma powodu, dla którego nie możesz mieć prostej strony HTML, do której wszystkie linki JavaScript mogą wskazywać w ich hrefsekcji w przypadku, gdy ktoś wyłączy JavaScript po zalogowaniu. Gorąco zachęcam do nadal zezwalania na ten mechanizm awaryjny. Coś takiego będzie zgodne z „sprawdzonymi metodami” i osiągnie Twój cel:

<a href="javascript_required.html" onclick="doSomething(); return false;">go</a>
cowgod
źródło
4
jak wartość href będzie wyświetlana użytkownikowi na pasku stanu? (pasek na dole) Rozważyłbym użycie nieco bardziej przyjaznego dla użytkownika linku np. „js.html? doSomething” strona może nadal być statycznym html. W ten sposób użytkownik wyraźnie zauważy różnicę między linkami.
Gene
7
Możesz zastąpić tę wartość atrybutem tytułu, np. <a href="javascript_required.html" title="Does Something" onclick="doSomething(); return false;"> go </a>
Conspicuous Compiler
Najlepszą praktyką powinno być rejestrowanie żądań na stronie javascript_required.html i funkcji, która spowodowała błąd.
Timo Huovinen
2
Czy myślałeś o konsekwencjach dla SEO?
DanielBlazquez,
Wygląda na to, że witryna javascripttoolbox.com Matta Kruse jest niedostępna i na sprzedaż.
showdev
10

Dlaczego miałbyś to robić, skoro możesz użyć addEventListener/ attachEvent? Jeśli nie ma żadnego hrefrównoważnika, nie używaj znaku <a>, użyj a <button>i odpowiednio go nadaj styl.

bez powiek
źródło
9
użycie przycisku zamiast linku w wielu przypadkach jest niewykonalne.
nickf
2
Ponieważ wygląda brzydko. Możesz dodać ikonę obok łącza. Trudno je sformatować tak samo w różnych przeglądarkach. Ogólnie rzecz biorąc, ludzie przechodzą do linków zamiast przycisków - spójrz na przepełnienie stosu.
Darryl Hein
2
Wygląda brzydko? Wygląda jak chcesz, żeby wyglądał. W rzeczywistości uważam, że przyciski mają większą elastyczność stylów niż linki, ponieważ są wbudowane, ale mogą prawidłowo przyjmować dopełnienie w różnych przeglądarkach. Wszystko, co można zrobić za pomocą linku, można zrobić za pomocą przycisku, w odniesieniu do CSS.
powiek
2
Zakres nie może skupiać się na klawiaturze.
bobince
3
Przycisk jest (sapiąc) semantycznie poprawny. Rozpiętość nie ma znaczenia semantycznego. Przycisk jest dokładnie tym , czego autor zamierza użyć, semantycznie.
powiek
5

Zapomniałeś innej metody:

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

Z kodem JavaScript:

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

Nie mogę komentować, która z opcji ma najlepszą obsługę lub która jest semantycznie najlepsza, ale powiem tylko, że zdecydowanie wolę ten styl, ponieważ oddziela on treść od kodu JavaScript. Utrzymuje cały kod JavaScript razem, co jest znacznie łatwiejsze w utrzymaniu (szczególnie jeśli stosujesz to do wielu linków), a nawet możesz umieścić go w zewnętrznym pliku, który można następnie spakować w celu zmniejszenia rozmiaru pliku i buforować przez przeglądarki klienta.

nickf
źródło
7
Jeśli masz 20 lub 30 różnych linków z JS, może to być dość żmudne i skończyć z dużą ilością JS.
Darryl Hein
nie jest to bardziej nużące niż brodzenie przez HTML w celu zmiany javascript. ... lub możesz użyć czegoś takiego jak jQuery, które może łatwo zmienić zdarzenia w wielu elementach naraz ... $ ('# menu a'). click (function () {..})
nickf
1
@JKirchartz Nie rozumiem, jak to jest głoszenie, jeśli za odpowiedzią kryją się powody. Jeśli czytasz pytanie, naprawdę jest to „która z tych 4 jest najlepsza”, a ja właśnie wskazałem, że istnieje inna opcja, której nie rozważał.
nickf
Nie przejmuj się, trololo, wybierając między ABC a D, nie wybiera się E.
JKirchartz,
3
@JKirchartz Tak, nie sądzę, że tak naprawdę rozumiesz cel przepełnienia stosu. Jeśli ktoś zapyta „Co lepiej zbudować aplikację internetową w: Cobol czy Fortran?” Można powiedzieć tej osobie, że nie rozważała wszystkich możliwości. Pytanie wyraźnie nie dotyczy tego, „która z tych czterech rzeczy jest najlepsza”.
nickf
3
<a href="#" onClick="DoSomething(); return false;">link</a>

Zrobię to lub:

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

Zależne od sytuacji. W przypadku większych aplikacji druga jest najlepsza, ponieważ konsoliduje wtedy kod zdarzenia.

Anik Islam Abhi
źródło
Jeśli masz 20 lub 30 różnych linków z JS, może to być dość żmudne i skończyć z dużą ilością JS.
Darryl Hein
a błędy, które wkradają się do twojego kodu, mogą być BARDZO trudne do debugowania. Te błędy pojawiają się bardzo łatwo, o czym świadczy pierwszy przykład. :)
nickf
1

Metoda nr 2 zawiera błąd składni w FF3 i IE7. Preferuję metody # 1 i # 3, ponieważ # 4 zabrudza identyfikator URI znakiem „#”, chociaż powoduje mniej wpisywania ... Oczywiście, jak zauważają inne odpowiedzi, najlepszym rozwiązaniem jest oddzielenie HTML od obsługi zdarzeń.

Pier Luigi
źródło
Metoda nr 2 czego? Pytania nie pozostają w tej samej kolejności, w jakiej je widziałeś.
Diodeus - James MacFarlane
Metoda nr 4 nie zepsuje identyfikatora URI, jeśli się upewnisz return false. Z tego powodu metoda nr 4 jest prawdopodobnie najlepsza (spośród wymienionych).
Már Örlygsson
2
@Diodeus, myślę, że Pier odnosił się do numerowanej listy w pytaniu , która w rzeczywistości istnieje od czasu wysłania pytania.
powiek
1

Zauważyłem jedną różnicę między tym:

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

i to:

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

jest tak, że w każdym przypadku masz:

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

wtedy w pierwszym przykładzie act2będzie działać przed, act1aw drugim przykładzie będzie odwrotnie.

JoelFan
źródło
1

Tylko nowoczesne przeglądarki

<!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>

Wiele przeglądarek

<!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>

Możesz to uruchomić zanim dokument będzie gotowy, klikanie przycisków zadziała, ponieważ dołączamy zdarzenie do dokumentu.

Źródła:

Timo Huovinen
źródło