Qual é a diferença entre os diferentes métodos de colocar o código JavaScript em um <a>?

87

Eu vi os seguintes métodos de colocar o código JavaScript em uma <a>tag:

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>

Eu entendo a ideia de tentar colocar um URL válido em vez de apenas código JavaScript, apenas no caso de o usuário não ter o JavaScript habilitado. Mas para o propósito desta discussão, preciso assumir que o JavaScript está habilitado (eles não podem fazer o login sem ele).

Pessoalmente, gosto da opção 2, pois ela permite que você veja o que será executado - especialmente útil ao depurar onde há parâmetros sendo passados ​​para a função. Tenho usado bastante e não encontrei problemas com o navegador.

Eu li que as pessoas recomendam 4, porque dá ao usuário um link real para seguir, mas realmente # não é "real". Não irá a lugar nenhum.

Há algum que não seja compatível ou seja muito ruim, quando você sabe que o usuário está com o JavaScript habilitado?

Pergunta relacionada: Href para links JavaScript: “#” ou “javascript: void (0)”? .

Darryl Hein
fonte
Pequeno problema de sintaxe: a escolha nº 2 deve ser - <a href="javascript:DoSomething();"> link </a> sem o "retorno"
DRosenfeld
Altere a resposta aceita para @eyelidlessness answer. Acho que é a melhor abordagem, porque se preocupa com a semântica.
Michał Perłakowski

Respostas:

69

Eu gosto bastante do artigo de práticas recomendadas de Javascript de Matt Kruse . Nele, ele afirma que usar a hrefseção para executar o código JavaScript é uma má ideia. Mesmo que você tenha declarado que seus usuários devem ter o JavaScript habilitado, não há razão para que você não possa ter uma página HTML simples para a qual todos os seus links JavaScript possam apontar para sua hrefseção, caso alguém desligue o JavaScript após o login. Eu recomendo fortemente que você ainda permita esse mecanismo de reserva. Algo como isso seguirá as "práticas recomendadas" e atingirá sua meta:

<a href="javascript_required.html" onclick="doSomething(); return false;">go</a>
deus-vaca
fonte
4
como o valor href será mostrado ao usuário na barra de status? (a barra na parte inferior) Eu consideraria usar um link um pouco mais amigável, por exemplo. "js.html? doSomething" a página ainda pode ser html estático. Desta forma, o usuário verá claramente a diferença entre os links.
Gene
7
Você pode substituir esse valor pelo atributo title, por exemplo, <a href="javascript_required.html" title="Does Something" onclick="doSomething(); return false;"> go </a>
Conspicuous Compiler
Deve ser uma prática recomendada registrar as solicitações na página javascript_required.html e registrar a função que causou o erro.
Timo Huovinen
2
Você já pensou nas consequências para o SEO?
DanielBlazquez
O javascripttoolbox.com de Matt Kruse parece estar offline e à venda.
showdev
10

Por que você faria isso quando pode usar addEventListener/ attachEvent? Se não houver um href-equivalente, não use um <a>, use um <button>e estilize-o de acordo.

sem pálpebras
fonte
9
usar um botão em vez de um link não é uma opção viável em muitos casos.
nickf
2
Porque parece feio. Você pode adicionar um ícone ao lado do link. Eles são difíceis de formatar da mesma forma em todos os navegadores. E, geralmente, as pessoas estão mudando para links em vez de botões - observe a maior parte do estouro de pilha.
Darryl Hein
2
Parece feio? Tem a aparência que você quiser. Na verdade, acho que os botões têm mais flexibilidade de estilo do que os links, pois são embutidos, mas podem receber preenchimento entre navegadores. Tudo o que pode ser feito com um link pode ser feito com um botão, no que diz respeito ao CSS.
ausência de pálpebras
2
O span não pode ser focado no teclado.
bobince
3
E o botão está (suspiro) semanticamente correto. Span é semanticamente sem sentido. Um botão é exatamente o que o autor pretende usar semanticamente.
ausência de pálpebras
5

Você esqueceu outro método:

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

Com o código JavaScript:

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

Não posso comentar qual das opções tem o melhor suporte ou qual é semanticamente a melhor, mas direi apenas que prefiro muito mais esse estilo porque separa o seu conteúdo do seu código JavaScript. Ele mantém todo o código JavaScript junto, o que é muito mais fácil de manter (especialmente se você estiver aplicando isso a muitos links), e você pode até colocá-lo em um arquivo externo que pode ser compactado para reduzir o tamanho do arquivo e armazenado em cache pelos navegadores clientes.

nickf
fonte
7
Se você tiver 20 ou 30 links diferentes com JS, isso pode se tornar muito tedioso e acabar com muito JS.
Darryl Hein
não é mais tedioso do que vasculhar HTML para alterar o javascript. ... ou você poderia usar algo como jQuery, que pode facilmente alterar os eventos em vários elementos de uma vez ... $ ('# menu a'). click (function () {..})
nickf
1
@JKirchartz Não vejo como é pregar se há razões por trás da resposta. Se você leu a pergunta, é realmente um "qual destes 4 é o melhor", e eu apenas apontei que há outra opção que ele não havia considerado.
nickf
Não se preocupe, trololo, ao escolher entre ABC e D, não se escolhe E.
JKirchartz
3
@JKirchartz Sim, eu não acho que você realmente entendeu o propósito do Stack Overflow então. Se alguém perguntar "Qual é o melhor para construir um aplicativo da web em: Cobol ou Fortran?" É aceitável dizer a essa pessoa que ela não considerou todas as possibilidades. A questão claramente não é "qual dessas quatro coisas é a melhor".
nickf
3
<a href="#" onClick="DoSomething(); return false;">link</a>

Eu farei isso, ou:

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

Dependendo da situação. Para aplicativos maiores, o segundo é melhor porque consolida seu código de evento.

Anik Islam Abhi
fonte
Se você tiver 20 ou 30 links diferentes com JS, isso pode se tornar muito tedioso e acabar com muito JS.
Darryl Hein
e bugs que se infiltram em seu código podem ser MUITO difíceis de depurar. Esses bugs aparecem com muita facilidade, como evidenciado pelo seu primeiro exemplo. :)
nickf
1

O método 2 tem um erro de sintaxe no FF3 e no IE7. Eu prefiro os métodos # 1 e # 3, porque # 4 suja o URI com '#' embora cause menos digitação ... Obviamente, como observado por outras respostas, a melhor solução é separar o html do tratamento de eventos.

Pier Luigi
fonte
Método 2 de quê? As perguntas não ficam na mesma ordem de quando VOCÊ as viu.
Diodeus - James MacFarlane
O método # 4 não bagunçará o URI se você fizer isso return false. Por esse motivo, o método nº 4 é provavelmente o melhor (dos listados).
Már Örlygsson
2
@Diodeus, creio que Pier estava se referindo à lista numerada dentro da pergunta , que de fato está lá desde que a pergunta foi postada em primeiro lugar.
ausência de pálpebras
1

Uma diferença que notei entre isso:

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

e isto:

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

é que se em qualquer caso você tiver:

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

então, para o primeiro exemplo, act2será executado antes act1e no segundo exemplo, será o contrário.

JoelFan
fonte
1

Apenas navegadores modernos

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

Cross-browser

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

Você pode executar isso antes que o documento esteja pronto, clicar nos botões funcionará porque anexamos o evento ao documento.

Fontes:

Timo Huovinen
fonte