Ao desenvolver sites modernos, os recursos JavaScript para trabalhar com o DOM são muito usados. Os scripts permitem exibir e ocultar os elementos dos quais as páginas são construídas, configurar as propriedades desses elementos. Objetos DOM que são interagidos com programas têm propriedades e métodos. Praticamente todos os programadores da web conhecem alguns deles, de acordo com o autor do material, cuja tradução publicamos hoje. Mas alguns dos quais ele quer falar aqui são muito menos famosos.

HTML e DOM
Primeiro, vamos falar sobre a diferença entre HTML e DOM. Por exemplo, um elemento regular
<table<
é obviamente código HTML. Esse elemento pode ser usado em arquivos html; possui um conjunto de atributos que determinam a aparência e o comportamento da tabela criada com sua ajuda. A rigor, a própria tag
<table>
não tem nada a ver com JavaScript. O relacionamento entre os elementos HTML presentes no documento e o código JavaScript é fornecido pelo DOM (Document Object Model). O DOM torna possível interagir com elementos HTML do código JavaScript como se fossem objetos.
Todos os elementos HTML têm suas próprias “interfaces DOM” que definem propriedades (geralmente são associadas a atributos de elementos HTML) e métodos. Por exemplo, o elemento
<table>
possui uma interface chamada
HTMLTableElement .
Você pode obter um link para um elemento, por exemplo, usando a seguinte construção:
const searchBox = document.getElementById('search-box');
Depois que o link para o elemento é recebido, o programador tem acesso às propriedades e métodos que esses elementos possuem. Por exemplo, você pode trabalhar com a propriedade
value
de um determinado campo de texto, uma vez que o link para ele é armazenado na variável
searchBox
usando uma estrutura no formato
searchBox.value
. Você pode colocar o cursor nesse campo de texto chamando seu método
searchBox.focus()
.
Talvez seja aqui que possamos concluir nosso "curso breve no DOM" e ir, de fato, para as propriedades e métodos pouco conhecidos das interfaces DOM dos elementos HTML.
Se você quiser ler e experimentar imediatamente, abra as ferramentas do desenvolvedor do navegador. Em particular, para obter um link para um determinado elemento da página, você pode selecioná-lo na árvore de elementos e, em seguida, usar a construção
$0
no
console . Para visualizar um item como um objeto, digite
dir($0)
no console. E, a propósito, se você se deparar com algo novo para você, tente explorá-lo usando o console.
No. 1: métodos de tabela
O elemento modesto
<table>
(que ainda ocupa o primeiro lugar entre as tecnologias usadas no desenvolvimento de layouts de páginas da web) possui um número razoável de métodos muito bons que simplificam bastante o processo de construção de tabelas.
Aqui estão alguns deles.
const tableEl = document.querySelector('table'); const headerRow = tableEl.createTHead().insertRow(); headerRow.insertCell().textContent = 'Make'; headerRow.insertCell().textContent = 'Model'; headerRow.insertCell().textContent = 'Color'; const newRow = tableEl.insertRow(); newRow.insertCell().textContent = 'Yes'; newRow.insertCell().textContent = 'No'; newRow.insertCell().textContent = 'Thank you';
Como você pode ver, aqui não usamos comandos como
document.createElement()
. E o método
.insertRow()
, se você o chamar diretamente na tabela, fornecerá até a adição de
<tbody>
. Não é maravilhoso?
# 2: método scrollIntoView ()
Você provavelmente sabe que se o link tiver uma construção como
#something
, depois de carregar a página, o navegador rolará automaticamente para o elemento com o
ID
correspondente? O método é conveniente, mas se o elemento de interesse para nós for renderizado após o carregamento da página, ele não funcionará. Veja como recriar esse padrão de comportamento:
document.querySelector(document.location.hash).scrollIntoView();
No. 3: propriedade oculta
Aqui consideramos uma propriedade, no entanto, provavelmente, ao acessar essa propriedade, um determinado setter será chamado, que é um método. De qualquer forma, lembre-se, você já usou o design mostrado abaixo para ocultar um elemento?
myElement.style.display = 'none'
Se você o usa, não deve mais fazê-lo. Para ocultar um elemento, basta escrever
true
para sua propriedade
hidden
:
myElement.hidden = true
# 4: método toggle ()
De fato, este não é um método de algum elemento. Este é um método de propriedade de elemento. Em particular, esse método permite adicionar classes a um elemento e removê-las usando a seguinte construção:
myElement.classList.toggle('some-class')
A propósito, se você já adicionou classes usando a construção
if
, lembre-se de que não precisa mais fazer isso e esqueça essa construção. O mesmo mecanismo é implementado usando o segundo parâmetro do método
toggle()
. Se essa expressão for avaliada como
true
, a classe passada para
toggle()
será adicionada ao elemento.
el.classList.toggle('some-orange-class', theme === 'orange');
Provavelmente, aqui você pode ter dúvidas sobre a adequação desse design. Afinal, o nome do método, "alternar", que, dado o fato de que a essência da ação executada está oculta nele, pode ser traduzida como "alternar", não contém nenhuma menção de que a alternância implica o cumprimento de uma determinada condição. No entanto, o design descrito acima existe nesta forma, embora os desenvolvedores do Internet Explorer provavelmente também o considerem estranho. Na implementação de
toggle()
segundo parâmetro não é fornecido. Portanto, embora tenha sido dito acima que aqueles que conhecem
toggle()
podem esquecer o construto
if
, esqueça-o, no entanto, não.
# 5: método querySelector ()
Você definitivamente já conhece a existência desse método, mas há uma suspeita de que exatamente 17% de vocês não sabem que ele pode ser usado na aplicação de qualquer elemento.
Por exemplo, a construção
myElement.querySelector('.my-class')
seleciona apenas os elementos que possuem a classe
my-class
e, ao mesmo tempo, são descendentes do elemento
myElement
.
# 6: método mais próximo ()
Todos os elementos que suportam a pesquisa de elementos pai têm esse método. Isso é algo como o inverso de
querySelector()
. Usando este método, por exemplo, você pode obter o título da seção atual:
myElement.closest('article').querySelector('h1');
Aqui, durante a pesquisa, primeiro o primeiro elemento pai
<article>
detectado e, em seguida, o primeiro elemento
<h1>
insere.
# 7: método getBoundingClientRect ()
O método
getBoundingClientRect()
retorna um pequeno objeto bem decorado contendo informações sobre o tamanho do elemento para o qual esse método foi chamado.
{ x: 604.875, y: 1312, width: 701.625, height: 31, top: 1312, right: 1306.5, bottom: 1343, left: 604.875 }
No entanto, usando esse método, deve-se tomar cuidado, principalmente, prestando atenção a dois pontos:
- A chamada desse método resulta em um redesenho da página. Dependendo do dispositivo em que a página é exibida e da complexidade da página, essa operação pode levar vários milissegundos. Considere isso se você deseja chamar esse método em certos fragmentos de código repetidos, por exemplo, ao executar animação.
- Nem todos os navegadores oferecem suporte a esse método.
# 8: método match ()
Suponha que precisamos verificar se um determinado elemento tem uma determinada classe.
Veja como resolver esse problema, aparentemente da maneira mais difícil:
if (myElement.className.indexOf('some-class') > -1) {
Aqui está outra opção, é melhor, mas também longe do ideal:
if (myElement.className.includes('some-class')) {
E aqui está a melhor maneira de resolver esse problema:
if (myElement.matches('.some-class')) {
# 9: método insertAdjacentElement ()
Esse método é semelhante ao
appendChild()
, mas fornece um pouco mais de poder sobre onde exatamente o elemento filho será adicionado.
Portanto, o comando
parentEl.insertAdjacentElement('beforeend', newEl)
semelhante ao comando
parentEl.appendChild(newEl)
, mas, usando o método
insertAdjacentElement()
, além do argumento
beforebegin
, você pode transmitir
beforebegin
,
afterbegin
e
afterend
, indicando o local em que precisa adicionar item.
No. 10: método contains ()
Você já quis saber se um elemento está dentro de outro? Eu preciso disso o tempo todo. Por exemplo, se durante o processamento de um evento de clique do mouse você precisar descobrir se ocorreu dentro da janela modal ou fora dela (o que significa que pode ser fechado), você pode usar a seguinte construção:
const handleClick = e => { if (!modalEl.contains(e.target)) modalEl.hidden = true; };
Aqui
modalEl
é um link para uma janela modal e
e.target
é qualquer elemento clicado. Curiosamente, quando uso essa técnica, nunca escrevo tudo certo da primeira vez, mesmo quando lembro que estou constantemente enganado e tento corrigir possíveis erros com antecedência.
# 11: método getAttribute ()
Talvez esse método possa ser chamado de mais inútil; no entanto, há uma situação na qual ele pode definitivamente ser útil.
Lembre-se, dissemos anteriormente que propriedades de objetos DOM geralmente são associadas a atributos de elementos HTML?
Um dos casos em que esse não é o caso é representado pelo atributo
href
, por exemplo, como aqui:
<a href="/animals/cat">Cat</a>
.
A construção
el.href
não retornará, como
el.href
esperar,
/animals/cat
. Isso ocorre porque o elemento
<a>
implementa a interface
HTMLHyperlinkElementUtils , que possui muitas propriedades auxiliares, como
protocol
e
hash
que ajudam a descobrir os detalhes dos links.
Uma dessas propriedades auxiliares é a propriedade
href
, que fornece uma URL completa que inclui tudo o que a URL relativa não possui no atributo
Como resultado, para obter exatamente o que está escrito no atributo
href
, você precisa usar a construção
el.getAttribute('href')
.
No. 12: três métodos do elemento <dialog>
O elemento relativamente novo
<dialog>
possui dois métodos úteis, mas bastante comuns, e um método que pode ser chamado de simplesmente maravilhoso. Portanto, os métodos
show()
e
close()
fazem exatamente o que você pode esperar deles, mostrando e ocultando a janela. Nós os chamamos de úteis, mas comuns. Mas o método
showModal()
mostrará o elemento
<dialog>
em cima de tudo o mais, exibindo-o no centro da janela. De fato, exatamente esse comportamento é normalmente esperado nas janelas modais. Ao trabalhar com esses elementos, você não precisa pensar na propriedade
z-index
, adicionar manualmente um fundo desfocado ou ouvir o evento de pressionar a tecla
Escape
para fechar a janela correspondente. O navegador sabe como as janelas modais devem funcionar e garantirá que tudo funcione como deveria.
# 13: método forEach ()
Às vezes, quando você obtém um link para uma lista de elementos, pode
forEach()
sobre esses elementos usando o método
forEach()
. Os loops
for()
são ontem. Suponha que precisamos listar todos os elementos
<a>
da página no log. Se fizermos isso como mostrado abaixo, encontraremos uma mensagem de erro:
document.getElementsByTagName('a').forEach(el => { console.log(el.href); });
Para resolver esse problema, você pode usar a seguinte construção:
document.querySelectorAll('a').forEach(el => { console.log(el.href); });
O ponto aqui é que métodos como
getElementsByTagName()
retornam um objeto do tipo
HTMLCollection
e
querySelectorAll
objeto
querySelectorAll
. É a interface do objeto
NodeList
nos dá acesso ao método
forEach()
(e também aos métodos
keys()
,
values()
e
forEach()
).
De fato, seria muito melhor se esses métodos simplesmente retornassem matrizes normais e não nos oferecessem algo que tivesse algum tipo de métodos aparentemente úteis que não são exatamente como matrizes. No entanto, não fique chateado por causa disso, pois as pessoas inteligentes da ECMA nos deram um ótimo método -
Array.from()
, que nos permite transformar tudo que se parece com matrizes em matrizes.
Como resultado, você pode escrever o seguinte:
Array.from(document.getElementsByTagName('a')).forEach(el => { console.log(el.href); });
E aqui está uma coisinha legal. Ao transformar em uma matriz o que costumava ser, temos a oportunidade de usar muitos métodos de matriz, como
map()
,
filter()
e
reduce()
. Aqui, por exemplo, como formar uma matriz de links externos na página:
Array.from(document.querySelectorAll('a')) .map(el => el.origin) .filter(origin => origin !== document.origin) .filter(Boolean);
A propósito, eu realmente gosto da construção
.filter(Boolean)
porque, quando a encontrei em algum momento no código que escrevi há muito tempo, mal consigo entender imediatamente seu significado.
No. 14: trabalhar com formulários
É muito provável que você saiba que o elemento
<form>
possui um método
submit()
. No entanto, é menos provável que você saiba que os formulários têm um método
reset()
e que eles têm um método
reportValidity()
, aplicável quando a validação do preenchimento de elementos do formulário é usada.
Ao trabalhar com formulários, você também pode usar a propriedade de
elements
, o que, por meio de um ponto, permite acessar os elementos do formulário usando seus atributos de
name
. Por exemplo, a construção
myFormEl.elements.email
retornará o elemento
<input name="email" />
pertencente ao formulário ("pertencer" não significa necessariamente "ser um descendente").
Deve-se notar aqui que a própria propriedade
elements
não retorna uma lista de elementos comuns. Ele retorna uma lista de controles (e essa lista, é claro, não é uma matriz).
Aqui está um exemplo. Se houver três botões de opção no formulário e todos eles tiverem o mesmo nome (
animal
), a construção
formEl.elements.animal
fornecerá um link para um conjunto de botões de opção (1 controle, 3 elementos HTML). E se você usar o
formEl.elements.animal.value
, ele fornecerá o valor do botão de opção selecionado pelo usuário.
Se você pensar bem, tudo parece bem estranho, então vamos lidar com o exemplo anterior:
formEl
é um elemento.elements
é um objeto HTMLFormControlsCollection que se assemelha a uma matriz, mas não é. Seus elementos não são necessariamente elementos HTML.animal
é um conjunto de vários botões de opção, apresentados como um conjunto devido ao fato de todos terem o mesmo name
(existe uma interface RadioNodeList projetada especificamente para trabalhar com botões de opção).value
usado para acessar o atributo value
do botão de opções ativo na coleção.
# 15: método select ()
Talvez no final do material seja melhor falar sobre algum método absolutamente surpreendente, embora talvez esse método seja uma revelação para alguém. Portanto, o método
.select()
permite selecionar o texto nos campos de entrada para os quais é chamado.
Sumário
Neste artigo, falamos sobre métodos e propriedades pouco conhecidos que podem ser usados para trabalhar com o conteúdo de páginas da web. Esperamos que você tenha encontrado aqui algo novo para si mesmo, e talvez não apenas novo, mas também útil.
Caros leitores! Você usa algum meio de interação programática com o conteúdo de páginas da web que não são amplamente conhecidas?
