Qual é a diferença entre addEventListenere onclick?
var h = document.getElementById("a");
h.onclick = dothing1;
h.addEventListener("click", dothing2);
O código acima reside juntos em um arquivo .js separado, e ambos funcionam perfeitamente.
Qual é a diferença entre addEventListenere onclick?
var h = document.getElementById("a");
h.onclick = dothing1;
h.addEventListener("click", dothing2);
O código acima reside juntos em um arquivo .js separado, e ambos funcionam perfeitamente.
Respostas:
Ambos estão corretos, mas nenhum deles é "melhor" por si só, e pode haver um motivo para o desenvolvedor escolher usar as duas abordagens.
Ouvintes de Eventos (addEventListener e attachEvent do IE)
As versões anteriores do Internet Explorer implementam o javascript de maneira diferente de praticamente qualquer outro navegador. Com versões menores que 9, você usa o método attachEvent[ doc ], assim:
element.attachEvent('onclick', function() { /* do stuff here*/ });
Na maioria dos outros navegadores (incluindo o IE 9 e superior), você usa addEventListener[ doc ], assim:
element.addEventListener('click', function() { /* do stuff here*/ }, false);
Usando essa abordagem ( eventos DOM Nível 2 ), você pode anexar um número teoricamente ilimitado de eventos a qualquer elemento. A única limitação prática é a memória do lado do cliente e outras preocupações de desempenho, que são diferentes para cada navegador.
Os exemplos acima representam o uso de uma função anônima [ doc ]. Você também pode adicionar um ouvinte de evento usando uma referência de função [ doc ] ou um encerramento [ doc ]:
var myFunctionReference = function() { /* do stuff here*/ }
element.attachEvent('onclick', myFunctionReference);
element.addEventListener('click', myFunctionReference , false);
Outra característica importante addEventListeneré o parâmetro final, que controla como o ouvinte reage a eventos de bolhas [ doc ]. Passei falso nos exemplos, o que é padrão para provavelmente 95% dos casos de uso. Não há argumento equivalente para attachEvent, ou ao usar eventos embutidos.
Eventos embutidos (HTML onclick = "" propriedade e element.onclick)
Em todos os navegadores que suportam javascript, você pode colocar um ouvinte de eventos em linha, o que significa diretamente no código HTML. Você provavelmente já viu isso:
<a id="testing" href="#" onclick="alert('did stuff inline');">Click me</a>
Os desenvolvedores mais experientes evitam esse método, mas ele faz o trabalho; é simples e direto. Você não pode usar encerramentos ou funções anônimas aqui (embora o próprio manipulador seja uma espécie de função anônima) e seu controle do escopo seja limitado.
O outro método que você menciona:
element.onclick = function () { /*do stuff here */ };
... é o equivalente a javascript embutido, exceto que você tem mais controle do escopo (já que está escrevendo um script em vez de HTML) e pode usar funções anônimas, referências de função e / ou fechamentos.
A desvantagem significativa dos eventos embutidos é que, diferentemente dos ouvintes de eventos descritos acima, você pode ter apenas um evento embutido atribuído. Eventos embutidos são armazenados como um atributo / propriedade do elemento [ doc ], o que significa que ele pode ser substituído.
Usando o exemplo <a>do HTML acima:
var element = document.getElementById('testing');
element.onclick = function () { alert('did stuff #1'); };
element.onclick = function () { alert('did stuff #2'); };
... quando você clica no elemento, você vê apenas "Did stuff # 2" - você substituiu o primeiro atribuído da onclickpropriedade pelo segundo valor e também substituiu a onclickpropriedade HTML embutida original . Confira aqui: http://jsfiddle.net/jpgah/ .
De um modo geral, não use eventos embutidos . Pode haver casos de uso específicos, mas se você não tiver 100% de certeza de que possui esse caso de uso, não precisará e não deverá usar eventos em linha.
Javascript moderno (angular e similares)
Desde que esta resposta foi postada originalmente, as estruturas javascript como Angular tornaram-se muito mais populares. Você verá um código como este em um modelo Angular:
<button (click)="doSomething()">Do Something</button>
Parece um evento embutido, mas não é. Esse tipo de modelo será transpilado para um código mais complexo que usa ouvintes de eventos nos bastidores. Tudo o que escrevi sobre eventos aqui ainda se aplica, mas você é removido do âmago da questão por pelo menos uma camada. Você deve entender as porcas e os parafusos, mas se as práticas recomendadas da estrutura JS moderna envolvem a gravação desse tipo de código em um modelo, não sinta que você está usando um evento embutido - não está.
Qual é melhor?
A questão é uma questão de compatibilidade e necessidade do navegador. Você precisa anexar mais de um evento a um elemento? Você vai no futuro? As probabilidades são, você vai. attachEvent e addEventListener são necessários. Caso contrário, um evento em linha pode parecer que eles resolveriam o problema, mas você está muito melhor preparado para um futuro que, embora possa parecer improvável, é previsível pelo menos. Há uma chance de você precisar mudar para ouvintes de eventos baseados em JS, então é melhor começar por aí. Não use eventos embutidos.
O jQuery e outras estruturas javascript encapsulam as diferentes implementações de navegador dos eventos do nível DOM 2 em modelos genéricos, para que você possa escrever código compatível com o navegador sem ter que se preocupar com a história do IE como rebelde. O mesmo código com o jQuery, todo o navegador e pronto para o rock:
$(element).on('click', function () { /* do stuff */ });
Porém, não se esgote e obtenha uma estrutura apenas para isso. Você pode facilmente rolar seu próprio pequeno utilitário para cuidar dos navegadores mais antigos:
function addEvent(element, evnt, funct){
if (element.attachEvent)
return element.attachEvent('on'+evnt, funct);
else
return element.addEventListener(evnt, funct, false);
}
// example
addEvent(
document.getElementById('myElement'),
'click',
function () { alert('hi!'); }
);
Experimente: http://jsfiddle.net/bmArj/
Levando tudo isso em consideração, a menos que o script que você está vendo tenha levado em consideração as diferenças do navegador de outra maneira (no código não mostrado na sua pergunta), a parte usada addEventListenernão funcionaria nas versões do IE inferiores a 9.
Documentação e Leitura Relacionada
function addEvent(e,n,f){return e.attachEvent?e.attachEvent('on'+n,f):e.addEventListener(n,f,!!0)}<< Com 98 caracteres, este é mais do que 40% menor!
A diferença que você poderia ver se tivesse outras funções:
var h = document.getElementById('a');
h.onclick = doThing_1;
h.onclick = doThing_2;
h.addEventListener('click', doThing_3);
h.addEventListener('click', doThing_4);
As funções 2, 3 e 4 funcionam, mas 1 não. Isso ocorre porque addEventListenernão substitui os manipuladores de eventos existentes, enquanto onclicksubstitui os onclick = fnmanipuladores de eventos existentes .
A outra diferença significativa, é claro, é que onclicksempre funcionará, enquanto addEventListenernão funciona no Internet Explorer antes da versão 9. Você pode usar o análogo attachEvent(que tem sintaxe um pouco diferente) no IE <9.
Nesta resposta, descreverei os três métodos de definição de manipuladores de eventos DOM.
element.addEventListener()Exemplo de código:
element.addEventListener() tem várias vantagens:
element.removeEventListener().useCaptureparâmetro, que indica se você deseja manipular o evento em sua fase de captura ou bolha . Consulte: Não é possível entender o atributo useCapture em addEventListener ..oneventpropriedades de elementos DOM, muitos programadores JavaScript inexperientes pensam que o nome do evento é por exemplo onclickou onload. oné não uma parte do nome do evento . Os nomes de eventos corretos são clicke load, e é assim que os nomes dos eventos são passados .addEventListener().element.onevent = function() {}(por exemplo onclick, onload)Exemplo de código:
Essa era uma maneira de registrar manipuladores de eventos no DOM 0. Agora é desencorajado, porque:
oneventpropriedade de volta ao seu estado inicial (ou seja null).window.onload, por exemplo:, window.onload = "test";ela não emitirá erros. Seu código não funcionaria e seria muito difícil descobrir o porquê. .addEventListener()no entanto, geraria um erro (pelo menos no Firefox): TypeError: O argumento 2 do EventTarget.addEventListener não é um objeto .oneventatributo HTML)Exemplo de código:
Da mesma forma element.onevent, agora é desencorajado. Além dos problemas que element.oneventtem, ele:
Content-Security-Policycabeçalho HTTP adequado para bloquear scripts embutidos e permitir scripts externos apenas de domínios confiáveis. Vejo Como a política de segurança de conteúdo funciona?Embora onclickfuncione em todos os navegadores, addEventListenernão funciona em versões mais antigas do Internet Explorer, que usa em seu attachEventlugar.
A desvantagem onclické que só pode haver um manipulador de eventos, enquanto os outros dois acionarão todos os retornos de chamada registrados.
Até onde eu sei, o evento "load" do DOM ainda funciona apenas muito limitado. Isso significa que ele só vai disparar para o window object, imagese <script>elementos por exemplo. O mesmo vale para a onloadatribuição direta . Não há diferença técnica entre os dois. Provavelmente.onload = tem uma melhor disponibilidade entre navegadores.
No entanto, você não pode atribuir um load eventa um <div>ou <span>elemento ou outros enfeites.
addEventListenerpode adicionar vários eventos, enquanto que com onclickisso não pode ser feito.onclickpode ser adicionado como um HTMLatributo, enquanto um addEventListenersó pode ser adicionado dentro de <script>elementos.addEventListener pode aceitar um terceiro argumento que pode interromper a propagação do evento.Ambos podem ser usados para manipular eventos. No entanto, addEventListenerdeve ser a escolha preferida, pois pode fazer tudo onclick e muito mais. Não use inline onclickcomo atributos HTML, pois isso mistura o javascript e o HTML, o que é uma prática ruim. Isso torna o código menos sustentável.
onclickhandlrs em linha com medo de rir da sala - mas geralmente os eventos são vinculados de maneiras muito piores e menos fáceis nos últimos anos. Classes como js-link, js-form-validationou atributos de dados com data-jspackage="init", não são de forma alguma melhores ... E com quantos anos você realmente usa a bolha de eventos? Pessoalmente, eu adoraria poder escrever um manipulador sem verificar se o alvo é realmente compatível com o meu elemento - ou ter que interromper a propagação em vários lugares devido a erros aleatórios.
Um detalhe ainda não foi observado: os navegadores de desktop modernos consideram que diferentes pressionamentos de botão são "cliques" para AddEventListener('click'e onclickpor padrão.
onclicke AddEventListenerclique em disparar no clique esquerdo e do meio.onclickacionado apenas no clique esquerdo, mas o AddEventListenerclique é acionado nos cliques esquerdo, central e direito.Além disso, o comportamento do clique do meio é muito inconsistente entre os navegadores quando há cursores de rolagem:
Também é importante notar que os eventos "clique" para qualquer elemento HTML selecionável pelo teclado, como inputtambém são acionados no espaço ou entram quando o elemento é selecionado.
Javascript tende a misturar tudo em objetos e isso pode torná-lo confuso. Tudo em um é a maneira JavaScript.
Essencialmente, onclick é um atributo HTML. Por outro lado, addEventListener é um método no objeto DOM que representa um elemento HTML.
Nos objetos JavaScript, um método é meramente uma propriedade que tem uma função como valor e que funciona contra o objeto ao qual está anexado (usando isso por exemplo).
No JavaScript, o elemento HTML representado pelo DOM terá seus atributos mapeados para suas propriedades.
É aqui que as pessoas ficam confusas porque o JavaScript mescla tudo em um único contêiner ou espaço para nome sem nenhuma camada de indireção.
Em um layout OO normal (que mescla pelo menos o espaço para nome das propriedades / métodos), você pode ter algo como:
domElement.addEventListener // Object(Method)
domElement.attributes.onload // Object(Property(Object(Property(String))))
Existem variações como ele poderia usar um getter / setter para onload ou HashMap para atributos, mas, no final das contas, seria assim. O JavaScript eliminou essa camada de indireção na expectativa de saber o que é o que há entre outras coisas. Ele mesclou domElement e atributos.
Para impedir a compatibilidade, como prática recomendada, use addEventListener. Como outras respostas falam sobre as diferenças a esse respeito, e não sobre as diferenças programáticas fundamentais, vou renunciar a isso. Essencialmente, em um mundo ideal, você realmente deve usar apenas * do HTML, mas em um mundo ainda mais ideal, você não deve fazer nada parecido com o HTML.
Por que é dominante hoje? É mais rápido de escrever, mais fácil de aprender e tende a funcionar.
O ponto principal da carga no HTML é conceder acesso ao método ou funcionalidade addEventListener em primeiro lugar. Ao usá-lo em JS, você está passando por HTML quando pode aplicá-lo diretamente.
Hipoteticamente, você pode criar seus próprios atributos:
$('[myclick]').each(function(i, v) {
v.addEventListener('click', function() {
eval(v.myclick); // eval($(v).attr('myclick'));
});
});
O que JS faz é um pouco diferente disso.
Você pode equiparar a algo como (para cada elemento criado):
element.addEventListener('click', function() {
switch(typeof element.onclick) {
case 'string':eval(element.onclick);break;
case 'function':element.onclick();break;
}
});
Os detalhes reais da implementação provavelmente diferem com uma variedade de variações sutis, tornando os dois ligeiramente diferentes em alguns casos, mas essa é a essência.
É sem dúvida um hack de compatibilidade que você pode fixar uma função em um atributo on, pois, por padrão, os atributos são todos strings.
De acordo com a MDN , a diferença é a seguinte:
addEventListener:
O método EventTarget.addEventListener () adiciona o objeto compatível compatível com EventListener especificado à lista de ouvintes de eventos para o tipo de evento especificado no EventTarget no qual é chamado. O destino do evento pode ser um elemento em um documento, o próprio documento, uma janela ou qualquer outro objeto que suporte eventos (como XMLHttpRequest).
onclick:
A propriedade onclick retorna o código do manipulador de eventos click no elemento atual. Ao usar o evento click para acionar uma ação, também considere adicionar essa mesma ação ao evento de pressionamento de tecla, para permitir o uso dessa mesma ação por pessoas que não usam mouse ou tela sensível ao toque. Sintaxe element.onclick = functionRef; onde functionRef é uma função - geralmente o nome de uma função declarada em outro lugar ou uma expressão de função. Consulte o "Guia JavaScript: Funções" para obter detalhes.
Há também uma diferença de sintaxe em uso, como você vê nos códigos abaixo:
addEventListener:
// Function to change the content of t2
function modifyText() {
var t2 = document.getElementById("t2");
if (t2.firstChild.nodeValue == "three") {
t2.firstChild.nodeValue = "two";
} else {
t2.firstChild.nodeValue = "three";
}
}
// add event listener to table
var el = document.getElementById("outside");
el.addEventListener("click", modifyText, false);
onclick:
function initElement() {
var p = document.getElementById("foo");
// NOTE: showAlert(); or showAlert(param); will NOT work here.
// Must be a reference to a function name, not a function call.
p.onclick = showAlert;
};
function showAlert(event) {
alert("onclick Event detected!");
}
Se você não estiver muito preocupado com o suporte ao navegador, existe uma maneira de religar a referência 'this' na função chamada pelo evento. Normalmente, ele apontará para o elemento que gerou o evento quando a função é executada, o que nem sempre é o que você deseja. A parte complicada é ao mesmo tempo remover o mesmo ouvinte de evento, conforme mostrado neste exemplo: http://jsfiddle.net/roenbaeck/vBYu3/
/*
Testing that the function returned from bind is rereferenceable,
such that it can be added and removed as an event listener.
*/
function MyImportantCalloutToYou(message, otherMessage) {
// the following is necessary as calling bind again does
// not return the same function, so instead we replace the
// original function with the one bound to this instance
this.swap = this.swap.bind(this);
this.element = document.createElement('div');
this.element.addEventListener('click', this.swap, false);
document.body.appendChild(this.element);
}
MyImportantCalloutToYou.prototype = {
element: null,
swap: function() {
// now this function can be properly removed
this.element.removeEventListener('click', this.swap, false);
}
}
O código acima funciona bem no Chrome e, provavelmente, há alguma restrição em tornar o "bind" compatível com outros navegadores.
O uso de manipuladores embutidos é incompatível com a Política de Segurança de Conteúdo, portanto, a addEventListenerabordagem é mais segura desse ponto de vista. É claro que você pode habilitar os manipuladores em linha unsafe-inline, mas, como o nome sugere, não é seguro, pois traz de volta toda a horda de explorações de JavaScript que o CSP impede.
Também deve ser possível estender o ouvinte através da criação de protótipos (se tivermos uma referência a ele e não for uma função anônima) - ou fazer o 'onclick' chamar uma chamada para uma biblioteca de funções (uma função chamando outras funções)
gostar
elm.onclick = myFunctionList
function myFunctionList(){
myFunc1();
myFunc2();
}
isso significa que nunca precisamos chocar a chamada onclick, basta alterar a função myFunctionList () para fazer o que quisermos, mas isso nos deixa sem controle das fases de captura / captura, portanto, isso deve ser evitado nos navegadores mais recentes.
caso alguém encontre esse tópico no futuro ...
element.onclick = function () {/ * faça coisas * /}
element.addEventListener ('clique', function () {/ * faz coisas * /}, false);
Aparentemente, eles fazem o mesmo: ouvem o evento click e executam uma função de retorno de chamada. No entanto, eles não são equivalentes. Se você precisar escolher entre os dois, isso poderá ajudá-lo a descobrir qual é o melhor para você.
A principal diferença é que o onclick é apenas uma propriedade e, como todas as propriedades do objeto, se você escrever mais de uma vez, ele será substituído . Com addEventListener () , podemos simplesmente ligar um manipulador de eventos ao elemento, e podemos chamá-lo sempre que precisarmos, sem nos preocuparmos com propriedades sobrescritas. Exemplo é mostrado aqui,
Tente: https://jsfiddle.net/fjets5z4/5/
Em primeiro lugar, fiquei tentado a continuar usando o onclick, porque é mais curto e parece mais simples ... e na verdade é. Mas não recomendo mais usá-lo. É como usar o JavaScript embutido. Atualmente, o uso de algo como - que é o JavaScript embutido - é altamente desencorajado (o CSS embutido também é desencorajado, mas esse é outro tópico).
No entanto, a função addEventListener (), apesar de padrão, simplesmente não funciona em navegadores antigos (Internet Explorer abaixo da versão 9), e essa é outra grande diferença. Se você precisar oferecer suporte a esses navegadores antigos, siga o caminho do onclick. Mas você também pode usar o jQuery (ou uma de suas alternativas): basicamente simplifica o seu trabalho e reduz as diferenças entre os navegadores, portanto, você pode economizar muito tempo.
var clickEvent = document.getElementByID("onclick-eg");
var EventListener = document.getElementByID("addEventListener-eg");
clickEvent.onclick = function(){
window.alert("1 is not called")
}
clickEvent.onclick = function(){
window.alert("2 is not called")
}
EventListener.addEventListener("click",function(){
window.alert("1 is called")
})
EventListener.addEventListener("click",function(){
window.alert("2 is also called")
})
addEventListener permite definir vários manipuladores, mas não é suportado no IE8 ou inferior.
O IE tem attachEvent, mas não é exatamente o mesmo.
O contexto referenciado pela 'this'palavra-chave no JavasSript é diferente.
veja o seguinte código:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<input id="btnSubmit" type="button" value="Submit" />
<script>
function disable() {
this.disabled = true;
}
var btnSubmit = document.getElementById('btnSubmit');
btnSubmit.onclick = disable();
//btnSubmit.addEventListener('click', disable, false);
</script>
</body>
</html>
O que ele faz é realmente simples. quando você clica no botão, o botão será desativado automaticamente.
Primeiro, quando você tenta conectar os eventos dessa maneira, o button.onclick = function(),
evento onclick será acionado clicando no botão; no entanto, o botão não será desativado porque não há uma ligação explícita entre o manipulador de eventos button.onclick e onclick. Se você depurar ver o 'this'objeto, poderá ver que ele se refere ao 'window'objeto.
Em segundo lugar, se você comentar btnSubmit.onclick = disable();e descomentar,
//btnSubmit.addEventListener('click', disable, false);poderá ver que o botão está desativado, pois dessa maneira há uma ligação explícita entre o evento button.onclick e o manipulador de eventos onclick. Se você depurar na função de desativação, poderá ver que 'this'se refere ao button controle não aowindow .
Isso é algo que eu não gosto no JavaScript, que é inconsistência. Btw, se você estiver usando jQuery ( $('#btnSubmit').on('click', disable);), ele usa ligação explícita.
btnSubmit.onclick = disable;(atribuir função, não chamá-lo). Em ambos os casos this, consultará o elemento button.
onclick é basicamente um addEventListener que executa especificamente uma função quando o elemento é clicado. Portanto, útil quando você tem um botão que executa operações simples, como um botão da calculadora. O addEventlistener pode ser usado para várias coisas, como executar uma operação quando o DOM ou todo o conteúdo é carregado, semelhante a window.onload, mas com mais controle.
Observe que você pode realmente usar mais de um evento com embutido ou, pelo menos, usando onclick, separando cada função com um ponto-e-vírgula, como este ....
Eu não escreveria uma função com inline, pois você pode ter problemas mais tarde e isso seria uma bagunça. Basta usá-lo para chamar funções já executadas no seu arquivo de script.
Qual você usa, suponho que depende do que você deseja. addEventListener para operações complexas e clique para simplificar. Eu já vi alguns projetos não anexarem um específico a elementos e, em vez disso, implementaria um listener de eventos mais global que determinaria se um toque estava em um botão e executaria determinadas tarefas, dependendo do que foi pressionado. Imo que poderia levar a problemas que eu pensaria e, embora pequeno, provavelmente, um desperdício de recursos, se o eventlistener tivesse que lidar com cada clique
function addEvent(element, myEvent, fnc) { return ((element.attachEvent) ? element.attachEvent('on' + myEvent, fnc) : element.addEventListener(myEvent, fnc, false)); }