Quais são os possíveis motivos para document.getElementById
, $("#id")
ou qualquer outro método DOM / seletor jQuery não encontrar os elementos?
Exemplos de problemas incluem:
- jQuery silenciosamente falhando ao vincular um manipulador de eventos
- jQuery "getter" métodos (
.val()
,.html()
,.text()
) retornandoundefined
- Um método DOM padrão retornando,
null
resultando em qualquer um dos vários erros:
TypeError não capturado: Não é possível definir a propriedade '...' nulo TypeError não capturado: Não é possível ler a propriedade '...' nulo
As formas mais comuns são:
TypeError não capturado: não é possível definir a propriedade 'onclick' de null
TypeError não capturado: Não é possível ler a propriedade 'addEventListener' de null
TypeError não capturado: não é possível ler a propriedade 'style' de null
javascript
jquery
dom
Felix Kling
fonte
fonte
Respostas:
O elemento que você estava tentando encontrar não estava no DOM quando o script foi executado.
A posição do seu script dependente de DOM pode ter um efeito profundo sobre seu comportamento. Os navegadores analisam documentos HTML de cima para baixo. Os elementos são adicionados ao DOM e os scripts são (geralmente) executados conforme são encontrados. Isso significa que a ordem é importante. Normalmente, os scripts não conseguem encontrar elementos que aparecem mais tarde na marcação, porque esses elementos ainda precisam ser adicionados ao DOM.
Considere a seguinte marcação; o script 1 não consegue encontrar o
<div>
script while 2 bem-sucedido:Então o que você deveria fazer? Você tem algumas opções:
Opção 1: mova seu script
Mova seu script para baixo na página, pouco antes da etiqueta do corpo de fechamento. Organizado dessa maneira, o restante do documento é analisado antes da execução do seu script:
Nota: A colocação de scripts na parte inferior geralmente é considerada uma prática recomendada .
Opção 2: jQuery
ready()
Adie seu script até que o DOM seja completamente analisado, usando :
$(handler)
Nota: Você pode simplesmente vincular a
DOMContentLoaded
ou mas cada uma tem suas ressalvas. O jQuery's oferece uma solução híbrida.window.onload
ready()
Opção 3: Delegação de Eventos
Quando um elemento gera um evento (desde que seja um evento de bolhas e nada interrompa sua propagação), cada pai na ancestralidade desse elemento também recebe o evento. Isso nos permite anexar um manipulador a um elemento existente e amostrar eventos à medida que surgem dos descendentes ... mesmo aqueles adicionados após o anexador. Tudo o que precisamos fazer é verificar o evento para ver se ele foi gerado pelo elemento desejado e, se houver, executar nosso código.
O jQuery's
on()
executa essa lógica para nós. Simplesmente fornecemos um nome de evento, um seletor para o descendente desejado e um manipulador de eventos:Nota: Normalmente, esse padrão é reservado para elementos que não existiam no momento do carregamento ou para evitar anexar uma grande quantidade de manipuladores. Também vale ressaltar que, enquanto eu anexei um manipulador
document
(para fins demonstrativos), você deve selecionar o ancestral confiável mais próximo.Opção 4: O
defer
atributoUse o
defer
atributo de<script>
.Para referência, aqui está o código desse script externo :
Nota: O
defer
atributo certamente parece uma bala mágica, mas é importante estar ciente das advertências ...1.
defer
só podem ser usadas para scripts externos, ou seja, aqueles que possuem umsrc
atributo.2. esteja ciente do suporte ao navegador , ou seja: implementação de bugs no IE <10
fonte
<head>
e usodefer
em scripts (não preciso oferecer suporte a navegadores incompatíveis antigos)defer
easync
têm um suporte bastante amplo, mesmo voltando a versões muito mais antigas do navegador. Eles têm a vantagem adicional de sinalizar de forma clara e explícita o comportamento pretendido. Lembre-se de que esses atributos funcionam apenas para scripts que especificam umsrc
atributo, ou seja: scripts externos. Pese os benefícios. Talvez use os dois? Sua chamada.Curto e simples: porque os elementos que você está procurando ainda não existem no documento.
Para o restante desta resposta, usarei
getElementById
como exemplo, mas o mesmo se aplica agetElementsByTagName
,querySelector
e a qualquer outro método DOM que selecione elementos.Razões possíveis
Há duas razões pelas quais um elemento pode não existir:
Um elemento com o ID passado realmente não existe no documento. Você deve verificar se o ID para o qual você passa
getElementById
realmente corresponde ao ID de um elemento existente no HTML (gerado) e se não digitou o ID incorretamente (os IDs diferenciam maiúsculas de minúsculas !).Aliás, na maioria dos navegadores contemporâneos , que implementam
querySelector()
equerySelectorAll()
métodos, a notação no estilo CSS é usada para recuperar um elemento porid
, por exemplodocument.querySelector('#elementID')
:, em oposição ao método pelo qual um elemento é recuperado por seuid
subdocument.getElementById('elementID')
; no primeiro, o#
personagem é essencial; no segundo, levaria o elemento a não ser recuperado.O elemento não existe no momento em que você chama
getElementById
.O último caso é bastante comum. Os navegadores analisam e processam o HTML de cima para baixo. Isso significa que qualquer chamada para um elemento DOM que ocorra antes que o elemento DOM apareça no HTML falhará.
Considere o seguinte exemplo:
A
div
aparece após oscript
. No momento em que o script é executado, o elemento não existe ainda egetElementById
irá retornarnull
.jQuery
O mesmo se aplica a todos os seletores com jQuery. O jQuery não encontrará elementos se você digitou incorretamente o seletor ou está tentando selecioná-los antes que eles realmente existam .
Um toque adicional é quando o jQuery não é encontrado porque você carregou o script sem protocolo e está sendo executado no sistema de arquivos:
essa sintaxe é usada para permitir que o script seja carregado via HTTPS em uma página com protocolo https: // e para carregar a versão HTTP em uma página com protocolo http: //
Tem o efeito colateral lamentável de tentar e não carregar
file://somecdn.somewhere.com...
Soluções
Antes de fazer uma chamada
getElementById
(ou qualquer método DOM), verifique se os elementos que você deseja acessar existem, ou seja, o DOM está carregado.Isso pode ser garantido simplesmente colocando seu JavaScript após o elemento DOM correspondente
nesse caso, você também pode colocar o código imediatamente antes da tag body de fechamento (
</body>
) (todos os elementos DOM estarão disponíveis no momento em que o script for executado).Outras soluções incluem ouvir os eventos
load
[MDN] ouDOMContentLoaded
[MDN] . Nesses casos, não importa onde, no documento, você coloca o código JavaScript, basta lembrar de colocar todo o código de processamento DOM nos manipuladores de eventos.Exemplo:
Consulte os artigos em quirksmode.org para obter mais informações sobre manipulação de eventos e diferenças no navegador.
jQuery
Primeiro, verifique se o jQuery está carregado corretamente. Use as ferramentas de desenvolvedor do navegador para descobrir se o arquivo jQuery foi encontrado e corrija o URL se não estiver (por exemplo, adicione o esquema
http:
ouhttps:
no início, ajuste o caminho etc.)Ouvir os eventos
load
/DOMContentLoaded
é exatamente o que o jQuery está fazendo com.ready()
[docs] . Todo o seu código jQuery que afeta o elemento DOM deve estar dentro desse manipulador de eventos.De fato, o tutorial do jQuery afirma explicitamente:
Como alternativa, você também pode usar a sintaxe abreviada:
Ambos são equivalentes.
fonte
ready
evento para refletir a sintaxe preferida "mais recente" ou é melhor deixá-lo como está para que funcione em versões mais antigas?$(window).load()
(e alternativas possivelmente sintáticas para o$(document).ready()
,$(function(){})
Ele parece estar relacionado, mas ele? Sente um pouco tangente ao ponto que você está fazendo..load
. Em relação às alternativas de sintaxe, elas podem ser consultadas na documentação, mas como as respostas devem ser independentes, pode valer a pena adicioná-las. Por outro lado, tenho certeza de que esse trecho específico do jQuery já foi respondido e provavelmente está coberto por outras respostas, e a ligação a ele pode ser suficiente..load
está obsoleto: api.jquery.com/load-event . Não sei se é apenas para imagens ouwindow
também.Razões pelas quais os seletores baseados em ID não funcionam
Soluções
Tente acessar o elemento após sua declaração ou, alternativamente, use coisas como
$(document).ready();
Para elementos provenientes de respostas do Ajax, use o
.bind()
método jQuery. As versões mais antigas do jQuery tinham.live()
o mesmo.Use as ferramentas [por exemplo, plug-in do desenvolvedor da web para navegadores] para encontrar IDs duplicados e removê-los.
fonte
Como o @FelixKling apontou, o cenário mais provável é que os nós que você está procurando ainda não existam.
No entanto, as práticas de desenvolvimento modernas geralmente podem manipular elementos do documento fora da árvore de documentos com DocumentFragments ou simplesmente desanexar / reconectar os elementos atuais diretamente. Essas técnicas podem ser usadas como parte do modelo de JavaScript ou para evitar operações excessivas de repintura / refluxo enquanto os elementos em questão estão sendo fortemente alterados.
Da mesma forma, a nova funcionalidade "Shadow DOM" lançada nos navegadores modernos permite que os elementos façam parte do documento, mas não possam ser consultados por document.getElementById e todos os seus métodos irmãos (querySelector, etc.). Isso é feito para encapsular a funcionalidade e ocultá-la especificamente.
Novamente, porém, é mais provável que o elemento que você está procurando simplesmente não esteja (ainda) no documento, e você deve fazer o que Felix sugere. No entanto, você também deve estar ciente de que essa é cada vez mais a única razão pela qual um elemento pode ser desconectado (temporariamente ou permanentemente).
fonte
Se o elemento que você está tentando acessar estiver dentro de um
iframe
e você tentar acessá-lo fora do contexto,iframe
isso também fará com que ele falhe.Se você deseja obter um elemento em um iframe, pode descobrir como aqui .
fonte
Se a ordem de execução do script não for o problema, outra causa possível do problema é que o elemento não está sendo selecionado corretamente:
getElementById
requer que a sequência passada seja o ID literalmente , e nada mais. Se você prefixar a sequência passada com a#
e o ID não iniciar com a#
, nada será selecionado:Da mesma forma, para
getElementsByClassName
, não prefixe a sequência passada com um.
:Com querySelector, querySelectorAll e jQuery, para combinar um elemento com um nome de classe específico, coloque um
.
diretamente antes da classe. Da mesma forma, para corresponder um elemento a um ID específico, coloque um#
diretamente antes do ID:As regras aqui são, na maioria dos casos, idênticas às dos seletores de CSS e podem ser vistas em detalhes aqui .
Para corresponder a um elemento que possui dois ou mais atributos (como dois nomes de classe ou um nome de classe e um
data-
atributo), coloque os seletores para cada atributo próximos um do outro na cadeia de seleção, sem um espaço para separá-los (porque um espaço indica o seletor descendente ). Por exemplo, para selecionar:use a string de consulta
.foo.bar
. Selecionaruse a string de consulta
.foo[data-bar="someData"]
. Para selecionar o<span>
abaixo:use
div.parent > span[data-username="bob"]
.Letras maiúsculas e ortografia são importantes para todos os itens acima. Se a capitalização for diferente ou a ortografia for diferente, o elemento não será selecionado:
Você também precisa garantir que os métodos tenham a capitalização e ortografia adequadas. Use um dos seguintes:
Qualquer outra ortografia ou capitalização não funcionará. Por exemplo,
document.getElementByClassName
lançará um erro.Certifique-se de passar uma string para esses métodos seletores. Se você passar algo que não é uma string para
querySelector
,getElementById
, etc, é quase certo que não vai funcionar.fonte
Quando tentei seu código, ele funcionou.
O único motivo pelo qual seu evento não está funcionando pode ser que seu DOM não estava pronto e seu botão com o ID "event-btn" ainda não estava pronto. E seu javascript foi executado e tentou vincular o evento a esse elemento.
Antes de usar o elemento DOM para ligação, esse elemento deve estar pronto. Existem muitas opções para fazer isso.
Opção1: você pode mover o código de ligação do evento para o evento ready do documento. Gostar:
Opção2: você pode usar o evento de tempo limite, para que a ligação seja atrasada por alguns segundos. gostar:
Opção 3: mova sua inclusão de javascript para a parte inferior da sua página.
Espero que isso ajude você.
fonte
o problema é que o elemento dom 'speclist' não é criado no momento em que o código javascript está sendo executado. Então, coloquei o código javascript dentro de uma função e chamei essa função no evento body onload.
fonte
Minha solução foi a de não usar o id de um elemento âncora:
<a id='star_wars'>Place to jump to</a>
. Aparentemente, o blazor e outras estruturas de spa têm problemas para se ancorar na mesma página. Para contornar isso eu tive que usardocument.getElementById('star_wars')
. No entanto, este não funcionou até que eu ponha o id em um elemento de parágrafo em vez disso:<p id='star_wars'>Some paragraph<p>
.Exemplo usando bootstrap:
fonte