Qual é a diferença entre propriedades e atributos em HTML?

408

Após as alterações feitas no jQuery 1.6.1, tentei definir a diferença entre propriedades e atributos em HTML.

Observando a lista nas notas de versão do jQuery 1.6.1 (próximo à parte inferior), parece que se pode classificar propriedades e atributos HTML da seguinte maneira:

  • Propriedades: tudo o que possui um valor booleano ou é calculado pelo UA, como selectedIndex.

  • Atributos: 'Atributos' que podem ser adicionados a um elemento HTML que não é booleano nem contém um valor gerado pelo UA.

Pensamentos?

schalkneethling
fonte
6
Possível duplicada de .prop () vs .attr ()
Naftali aka Neal

Respostas:

826

Ao escrever o código-fonte HTML, você pode definir atributos nos seus elementos HTML. Então, uma vez que o navegador analise seu código, um nó DOM correspondente será criado. Este nó é um objeto e, portanto, possui propriedades .

Por exemplo, este elemento HTML:

<input type="text" value="Name:">

possui 2 atributos ( typee value).

Depois que o navegador analisa esse código, um objeto HTMLInputElement será criado e esse objeto conterá dezenas de propriedades como: accept, accessKey, align, alt, atributos, autofoco, baseURI, verificado, childElementCount, childNodes, children, classList, className, clientHeight, etc.

Para um determinado objeto do nó DOM, propriedades são as propriedades desse objeto e atributos são os elementos da attributespropriedade desse objeto.

Quando um nó DOM é criado para um determinado elemento HTML, muitas de suas propriedades se relacionam a atributos com nomes iguais ou semelhantes, mas não é um relacionamento individual. Por exemplo, para este elemento HTML:

<input id="the-input" type="text" value="Name:">

o nó DOM correspondente terá id, typee valuepropriedades (entre outras):

  • A idpropriedade é uma propriedade refletida para o idatributo: Obter a propriedade lê o valor do atributo e definir a propriedade grava o valor do atributo. idé uma propriedade refletida pura , não modifica ou limita o valor.

  • A typepropriedade é uma propriedade refletida para o typeatributo: Obter a propriedade lê o valor do atributo e definir a propriedade grava o valor do atributo. typenão é uma propriedade refletida pura porque está limitada a valores conhecidos (por exemplo, os tipos válidos de uma entrada). Se você tivesse <input type="foo">, então theInput.getAttribute("type")te dá, "foo"mas theInput.typete dá "text".

  • Por outro lado, a valuepropriedade não reflete o valueatributo. Em vez disso, é o valor atual da entrada. Quando o usuário altera manualmente o valor da caixa de entrada, a valuepropriedade refletirá essa alteração. Portanto, se o usuário "John"inserir na caixa de entrada, então:

    theInput.value // returns "John"

    enquanto que:

    theInput.getAttribute('value') // returns "Name:"

    A valuepropriedade reflete o conteúdo de texto atual dentro da caixa de entrada, enquanto o valueatributo contém o conteúdo de texto inicial do valueatributo no código-fonte HTML.

    Portanto, se você quiser saber o que está atualmente dentro da caixa de texto, leia a propriedade Se você, no entanto, deseja saber qual era o valor inicial da caixa de texto, leia o atributo Ou você pode usar a defaultValuepropriedade, que é um reflexo puro do valueatributo:

    theInput.value                 // returns "John"
    theInput.getAttribute('value') // returns "Name:"
    theInput.defaultValue          // returns "Name:"

Existem várias propriedades que refletem diretamente seu atributo ( rel, id), alguns são reflexos diretos com nomes ligeiramente diferentes ( htmlForreflete o foratributo, classNamereflete o classatributo), muitos que refletem seu atributo, mas com restrições / modificações ( src, href, disabled, multiple), e assim por em. A especificação abrange os vários tipos de reflexão.

Šime Vidas
fonte
1
Hey Sime, acho que isso é bastante ambíguo, especialmente se você der uma olhada aqui: w3.org/TR/html4/index/attributes.html , e não houver uma resposta clara. Um precisa basicamente de seguir o que está indicado no resumo no blog jQuery e, mesmo assim, aquele será mapeado para o outro e trabalhar em ambos os casos com uma pequena queda de performance você deve usar incorretamente prop quando você precisa usar attr
schalkneethling
4
@oss Seu link se refere a uma lista de atributos HTML. Essa lista não é ambígua - esses são atributos.
Šime Vidas 15/05
existem alguns documentos sobre a relação? @ ŠimeVidas
SKing7
3
Onde eu poderia encontrar uma lista completa de atributos para propriedades (como for-> htmlFor) e da mesma forma uma lista de propriedades que recebem seu valor inicial de um atributo, mas não o refletem ( input.value). Espero que isso esteja em algum lugar na fonte de uma biblioteca como github.com/Matt-Esch/virtual-dom, mas não está realmente documentado.
Sstur 02/07/19
1
@Pim Eu não li, mas essa série de artigos em 4 partes parece um ótimo recurso: twitter.com/addyosmani/status/1082177515618295808
Šime Vidas
53

Depois de ler a resposta de Sime Vidas , procurei mais e encontrei uma explicação muito direta e fácil de entender nos documentos angulares .

Atributo HTML vs. Propriedade DOM


Os atributos são definidos por HTML. As propriedades são definidas pelo DOM (Document Object Model).

  • Alguns atributos HTML têm mapeamento 1: 1 para propriedades. idé um exemplo.

  • Alguns atributos HTML não têm propriedades correspondentes. colspané um exemplo.

  • Algumas propriedades do DOM não têm atributos correspondentes. textContent é um exemplo.

  • Muitos atributos HTML parecem mapear para propriedades ... mas não da maneira que você imagina!

Essa última categoria é confusa até que você entenda esta regra geral:

Os atributos inicializam as propriedades do DOM e são concluídas. Os valores da propriedade podem mudar; valores de atributo não podem.

Por exemplo, quando o navegador é renderizado <input type="text" value="Bob">, ele cria um nó DOM correspondente com uma valuepropriedade inicializada para "Bob".

Quando o usuário digita "Sally" na caixa de entrada, a value propriedade do elemento DOM se torna "Sally". Mas o value atributo HTML permanece inalterado conforme você descobre se você perguntar ao elemento de entrada sobre esse atributo: input.getAttribute('value')retorna "Bob".

O atributo HTML valueespecifica o valor inicial ; a value propriedade DOM é o valor atual .


O disabledatributo é outro exemplo peculiar. A disabledpropriedade de um botão é falsepor padrão, portanto, o botão está ativado. Quando você adiciona o disabledatributo, apenas sua presença inicializa a disabledpropriedade do botão para trueque o botão seja desativado.

Adicionar e remover o disabledatributo desativa e ativa o botão. O valor do atributo é irrelevante, e é por isso que você não pode ativar um botão escrevendo<button disabled="false">Still Disabled</button>.

A configuração da disabled propriedade do botão desativa ou ativa o botão. O valor da propriedade é importante.

O atributo HTML e a propriedade DOM não são a mesma coisa, mesmo quando eles têm o mesmo nome.

investigador
fonte
Este exemplo não está certo: o colspanatributo tem a colSpanpropriedade ... Então, qual atributo não tem uma propriedade relacionada agora?
Robert Siemer 15/02
46

As respostas já explicam como os atributos e as propriedades são tratados de maneira diferente, mas eu realmente gostaria de salientar como isso é totalmente insano . Mesmo que seja em certa medida a especificação.

É uma loucura ter alguns dos atributos (por exemplo , id, classe, foo, barra ) para reter apenas um tipo de valor no DOM, enquanto alguns atributos (por exemplo , verificados, selecionados ) para reter dois valores; isto é, o valor "quando foi carregado" e o valor do "estado dinâmico". (O DOM não deve representar o estado do documento em toda a sua extensão?)

É absolutamente essencial que dois campos de entrada , por exemplo, um texto e uma caixa de seleção se comportem da mesma maneira . Se o campo de entrada de texto não reter um valor separado "quando foi carregado" e o valor "dinâmico atual", por que a caixa de seleção? Se a caixa de seleção possui dois valores para o atributo marcado , por que não possui dois para seus atributos de classe e ID ? Se você espera alterar o valor de um campo de texto * input * e espera que o DOM (ou seja, a "representação serializada") mude e reflita essa mudança, por que diabos você não esperaria o mesmo de um campo de entrada de caixa de seleção tipo no atributo verificado?

A diferenciação de "é um atributo booleano" simplesmente não faz sentido para mim, ou é, pelo menos, não uma razão suficiente para isso.

sibidiba
fonte
21
Esta não é uma resposta, mas estou de acordo com você; é totalmente insano.
Samuel
Sim, esse conceito é péssimo e não deve ser tão padronizado. Esse foi um dos casos (como innerHTML, por exemplo), que era bom no IE antigo e deveria ter sido adotado pelos padrões. Propriedades e atributos foram sincronizados sempre que possível, até atributos personalizados, tornando a sintaxe js dot legível muito agradável. O HTML5 torna as tags HTML personalizadas cidadãos de primeira classe; os atributos personalizados também devem ser. Esse recurso está sendo removido porque o IE antigo ainda é um problema real - só agora estamos vendo muitas empresas tradicionalmente presas ao IE para sistemas antigos, agora encontrando-as quebradas no IE10.
precisa saber é o seguinte
48
Não é insano. Você entendeu mal. O checkedatributo é representado pela defaultCheckedpropriedade (da mesma forma que para uma entrada de texto, o valueatributo é representado pela defaultValuepropriedade). Uma segunda propriedade, checkedé necessária para representar se a caixa de seleção está marcada porque esta é uma parte intrínseca da funcionalidade de uma caixa de seleção: é interativa e pode ser alterada (e redefinida para o padrão, se um botão de redefinição de formulário estiver presente) pelo usuário , de uma maneira que outro atributo como idnão é. Não tem nada a ver com o fato de ser um atributo booleano.
Tim Baixo
3
@ TimDown - Obrigado. Isso realmente me superou na WTF? corcunda.
pedz
12
@TimDown Ainda sinto que é "insano" porque qualquer abordagem lógica faria com que o nome da propriedade e o nome do atributo correspondessem, ou pelo menos não tivesse um nome de atributo e um nome de propriedade que não sejam relacionados (ou seja, o atributo verificado se refere ao defaultChecked enquanto a propriedade marcada não estiver relacionada). De fato, a abordagem lógica que todos assumem é o caso no início, não separando os atributos e propriedades. Os atributos não devem ser imutáveis, mas sempre devem refletir os valores da propriedade. Não deveria haver uma distinção entre os dois.
dallin
10

bem, eles são especificados pelo w3c o que é um atributo e o que é uma propriedade http://www.w3.org/TR/SVGTiny12/attributeTable.html

mas atualmente o attr e o prop não são tão diferentes e existem quase os mesmos

mas eles preferem adereços para algumas coisas

Resumo de uso preferido

O método .prop () deve ser usado para atributos / propriedades booleanos e para propriedades que não existem em html (como window.location). Todos os outros atributos (aqueles que você pode ver no html) podem e devem continuar sendo manipulados com o método .attr ().

Bem, na verdade você não precisa alterar algo se usar attr ou prop ou ambos, ambos funcionam, mas eu vi no meu próprio aplicativo que prop funcionava onde o atrr não fazia, então peguei no meu 1.6 app prop =)

Daniel Ruf
fonte
Ei Daniel, eu li isso. Parece que existe uma definição clara para separar os dois, pois parte do que o Sime menciona abaixo também pode ser adicionado ao elemento HTML, por exemplo, alt. Continuará a ler algumas das especificações HTML e verificar se há realmente uma maneira de distinguir claramente as duas na prática.
Schalkneethling 15/05
3
Esse documento está relacionado ao SVG, não ao HTML.
Luzado
5

Diferença de propriedades e atributos HTML:

Vamos primeiro examinar as definições dessas palavras antes de avaliar qual é a diferença no HTML:

Definição em inglês:

  • Os atributos estão se referindo a informações adicionais de um objeto.
  • As propriedades estão descrevendo as características de um objeto.

No contexto HTML:

Quando o navegador analisa o HTML, ele cria uma estrutura de dados em árvore que basicamente é uma representação na memória do HTML. A estrutura de dados da árvore contém nós que são elementos e texto HTML. Os atributos e propriedades relacionados a isso são da seguinte maneira:

  • Atributos são informações adicionais que podemos colocar no HTML para inicializar determinadas propriedades do DOM.
  • As propriedades são formadas quando o navegador analisa o HTML e gera o DOM. Cada um dos elementos no DOM possui seu próprio conjunto de propriedades, todas definidas pelo navegador. Algumas dessas propriedades podem ter seu valor inicial definido por atributos HTML. Sempre que uma propriedade DOM for alterada e influenciar a página renderizada, ela será renderizada imediatamente

Também é importante perceber que o mapeamento dessas propriedades não é 1 para 1. Em outras palavras, nem todos os atributos que fornecemos em um elemento HTML terão uma propriedade DOM denominada semelhante.

Além disso, possui diferentes elementos DOM, diferentes propriedades. Por exemplo, um <input>elemento tem uma propriedade de valor que não está presente em uma <div>propriedade.

Exemplo:

Vamos pegar o seguinte documento HTML:

 <!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">  <!-- charset is a attribute -->
  <meta name="viewport" content="width=device-width"> <!-- name and content are attributes -->
  <title>JS Bin</title>
</head>
<body>
<div id="foo" class="bar foobar">hi</div> <!-- id and class are attributes -->
</body>
</html>

Em seguida, inspecionamos o <div>console JS:

 console.dir(document.getElementById('foo'));

Vemos as seguintes propriedades do DOM (chrome devtools, nem todas as propriedades mostradas):

propriedades e atributos html

  • Podemos ver que o ID do atributo no HTML agora também é uma propriedade de ID no DOM. O ID foi inicializado pelo HTML (embora possamos alterá-lo com javascript).
  • Podemos ver que o atributo de classe no HTML não possui propriedade de classe correspondente ( classé a palavra-chave reservada em JS). Mas na verdade 2 propriedades, classListe className.
Willem van der Veen
fonte