Ouvi muitas vezes que o uso de eventos JavaScript, como onClick()
HTML, é uma prática ruim, porque não é bom para semântica. Gostaria de saber quais são as desvantagens e como corrigir o código a seguir?
<a href="#" onclick="popup('/map/', 300, 300, 'map'); return false;">link</a>
javascript
html
NiLL
fonte
fonte
#
, qualquer um que optar por desativar o javascript ficará preso e não poderá fazer nada. Para alguns sites, isso é uma coisa boa, mas, para simplesmente abrir uma janela, é completamente estúpido não fornecer um link "real".<button>
, porque os links devem apontar para um recurso real. É mais semântico e é mais claro para os usuários de leitores de tela.Respostas:
Você provavelmente está falando de Javascript discreto , que seria assim:
com a lógica em um arquivo javascript central parecido com isto:
As vantagens são
fonte
onClick
. Você também pode escrever testes de unidade, se desejar, contra seus scripts, o que também é muito difícil, eu diria que se o código estiver dentro deonClick
e nenhuma lógica for separada. Pessoalmente, não tenho problema em depurar JavaScript discreto e os benefícios de gerenciar e testar o código JavaScript são muito grandes para não usá-lo.onclick
mapeamento mais explícito dos relacionamentos causais entre a interação do elemento e o efeito (chamada de função), além de reduzir a carga cognitiva. Muitas lições colocam os alunos em uma série deaddEventListener
idéias, dentro de uma sintaxe mais difícil. Além disso, estruturas recentes baseadas em componentes como Riot e React usam oonclick
atributo e estão mudando a noção do que deve ser a separação. Transferir do HTMLonclick
para um componente que suporte isso pode ser um processo de "etapa" mais eficaz para o aprendizado.Se você estiver usando jQuery, então:
HTML:
JS:
Isso tem o benefício de continuar trabalhando sem JS ou se o usuário clicar no meio do link.
Isso também significa que eu poderia lidar com pop-ups genéricos reescrevendo novamente para:
HTML:
JS:
Isso permitiria adicionar um pop-up a qualquer link, apenas fornecendo a classe pop-up.
Essa idéia pode ser estendida ainda mais assim:
HTML:
JS:
Agora posso usar o mesmo código para muitos pop-ups em todo o site, sem ter que escrever um monte de coisas onclick! Yay para reutilização!
Isso também significa que, se mais tarde eu decidir que os pop-ups são uma má prática (o que são!) E que eu quero substituí-los por uma janela modal no estilo lightbox, eu posso mudar:
para
e todos os meus pop-ups em todo o site agora estão funcionando de maneira totalmente diferente. Eu poderia até fazer a detecção de recursos para decidir o que fazer em um pop-up ou armazenar a preferência dos usuários para permitir ou não. Com o on-click on-line, isso exige um grande esforço de copiar e colar.
fonte
Com aplicativos JavaScript muito grandes, os programadores estão usando mais encapsulamento de código para evitar poluir o escopo global. E para disponibilizar uma função para a ação onClick em um elemento HTML, ela deve estar no escopo global.
Você pode ter visto arquivos JS parecidos com este ...
Essas são Expressões de Função Invocadas Imediatamente (IIFEs) e qualquer função declarada nelas só existirá dentro de seu escopo interno.
Se você declarar
function doSomething(){}
dentro de um IIFE, em seguida, façadoSomething()
a ação onClick de um elemento em sua página HTML, você receberá um erro.Se, por outro lado, você criar um eventListener para esse elemento dentro do IIFE e chamar
doSomething()
quando o ouvinte detectar um evento de clique, você será bom porque o ouvinte edoSomething()
compartilhará o escopo do IIFE.Para pequenos aplicativos da Web com uma quantidade mínima de código, isso não importa. Mas se você deseja escrever grandes bases de códigos que podem ser mantidas,
onclick=""
é um hábito que você deve evitar.fonte
Não é bom por vários motivos:
eval
A coisa mais simples seria adicionar um
name
atributo ao seu<a>
elemento, então você poderia fazer:embora a melhor prática moderna seja usar
id
um nome em vez de um nome e usá-lo emaddEventListener()
vez de usar,onclick
pois isso permite vincular várias funções a um único evento.fonte
addEventListener()
e por quê.Há algumas razões:
Acho que ajuda na manutenção da separação da marcação, ou seja, os scripts HTML e do lado do cliente. Por exemplo, o jQuery facilita a adição de manipuladores de eventos programaticamente.
O exemplo que você deu seria quebrado em qualquer agente de usuário que não suporte javascript ou que tenha o javascript desativado. O conceito de aprimoramento progressivo incentivaria um hiperlink simples
/map/
para agentes de usuários sem javascript e, em seguida, adicionaria um manipulador de cliques de forma significativa para agentes de usuários que suportam javascript.Por exemplo:
Marcação:
Javascript:
fonte
<a href="https://stackoverflow.com/map/" onclick="popup('/map/', 300, 300, 'map'); return false;">link</a>
Revisão
A abordagem discreta do JavaScript foi boa no PAST - especialmente a vinculação do manipulador de eventos no HTML foi considerada uma má prática (principalmente porque o
onclick events run in the global scope and may cause unexpected error
que foi mencionado pelo YiddishNinja )Contudo...
Atualmente, parece que essa abordagem está um pouco desatualizada e precisa de alguma atualização. Se alguém quiser ser desenvolvedor profissional de front-end e escrever aplicativos grandes e complicados, precisará usar estruturas como Angular, Vue.js, etc ... No entanto, essas estruturas geralmente usam (ou permitem usar) modelos HTML em que manipuladores de eventos são vinculados no código html-template diretamente e isso é muito útil, claro e eficaz - por exemplo, no modelo angular geralmente as pessoas escrevem:
Em js / html bruto, o equivalente a isso será
A diferença é que, no
onclick
evento js bruto , é executado no escopo global - mas as estruturas fornecem encapsulamento.Então onde está o problema?
O problema é quando o programador iniciante que sempre ouviu falar que o html-onclick é ruim e que sempre usa
btn.addEventListener("onclick", ... )
quer usar alguma estrutura com modelos (addEventListener
também tem desvantagens - se atualizarmos o DOM de maneira dinâmica usandoinnerHTML=
(o que é bastante rápido )), perderemos eventos manipuladores se ligam dessa maneira). Então, ele enfrentará algo como maus hábitos ou abordagem incorreta do uso da estrutura - e ele usará a estrutura de maneira muito ruim - porque ele se concentrará principalmente na parte js e não na parte do modelo (e produzirá incertos e difíceis de manter código). Para mudar esses hábitos, ele perderá muito tempo (e provavelmente precisará de um pouco de sorte e professor).Então, na minha opinião, com base na experiência com meus alunos, seria melhor para eles se eles usassem html-handlers-bind no início. Como eu digo, é verdade que os manipuladores são chamados no escopo global, mas nesse estágio os alunos geralmente criam aplicativos pequenos e fáceis de controlar. Para escrever aplicativos maiores, eles escolhem algumas estruturas.
Então o que fazer?
Podemos ATUALIZAR a abordagem JavaScript Discreta e permitir manipuladores de eventos de ligação (eventualmente com parâmetros simples) em html (mas apenas manipulador de ligação - não colocar lógica no onclick como no quesiton OP). Portanto, na minha opinião, em js / html bruto, isso deve ser permitido
ou
Mostrar snippet de código
Mas exemplos abaixo NÃO devem ser permitidos
A realidade muda, nosso ponto de vista também deve
fonte
addEventListener
. Anúncio 2. Sim, eles podem ser substituídos (no entanto, geralmente ninguém o faz) - onde está o problema? Anúncio 3. O manipulador não será acionado após excluir oÉ um
novoparadigma chamado " JavaScript Discreto ". O "padrão da web" atual diz para separar funcionalidade e apresentação.Não é realmente uma "má prática", mas a maioria dos novos padrões deseja que você use ouvintes de eventos em vez de incorporar o JavaScript.
Além disso, isso pode ser apenas uma coisa pessoal, mas acho que é muito mais fácil ler quando você usa ouvintes de eventos, especialmente se você tiver mais de uma instrução JavaScript que deseja executar.
fonte
Sua pergunta irá desencadear uma discussão, suponho. A idéia geral é que é bom separar comportamento e estrutura. Além disso, um manipulador de cliques inline deve ser
eval
levado a 'tornar-se' uma função javascript real. E é bem antiquado, apesar de ser um argumento bastante instável. Ah, bem, leia um pouco sobre isso @ quirksmode.orgfonte
desempenho e a eficiência.
fonte
Mais dois motivos para não usar manipuladores embutidos:
Eles podem exigir problemas de escape de cotações tediosas
Dada uma sequência arbitrária , se você quiser construir um manipulador em linha que chame uma função com essa sequência, para a solução geral, será necessário escapar dos delimitadores de atributo (com a entidade HTML associada) e você precisa escapar do delimitador usado para a sequência dentro do atributo, como o seguinte:
Isso é incrivelmente feio. No exemplo acima, se você não substituísse os
'
, resultaria em um SyntaxError, porquealert('foo'"bar')
não é uma sintaxe válida. Se você não substituísse"
s, o navegador o interpretaria como um fim para oonclick
atributo (delimitado com"
s acima), que também estaria incorreto.Se alguém usa habitualmente manipuladores em linha, um teria que ter certeza de lembrar fazer algo semelhante ao anterior (e fazê-lo direito ) de cada vez , o que é tedioso e difícil de entender à primeira vista. Melhor evitar manipuladores inline inteiramente para que a cadeia arbitrária possa ser usada em um fechamento simples:
Isso não é muito melhor?
A cadeia de escopo de um manipulador em linha é extremamente peculiar
O que você acha que o código a seguir registrará?
Experimente, execute o snippet. Provavelmente não é o que você estava esperando. Por que produz o que faz? Porque os manipuladores em linha executam dentro de
with
blocos. O código acima está dentro de trêswith
blocos: um para odocument
, um para o<form>
e um para o<button>
:Mostrar snippet de código
Como
disabled
é uma propriedade do botão, a referênciadisabled
dentro do manipulador embutido refere-se à propriedade do botão, não àdisabled
variável externa . Isso é bastante contra-intuitivo.with
tem muitos problemas: pode ser a fonte de erros confusos e diminui significativamente o código. Nem sequer é permitido em modo estrito. Mas com manipuladores inline, você é forçado a executar o código por meio dewith
s - e não apenas por umwith
, mas por várioswith
s aninhados . É louco.with
nunca deve ser usado no código. Como os manipuladores inline exigem implicitamente,with
juntamente com todo o seu comportamento confuso, os manipuladores inline também devem ser evitados.fonte