{"id":44006,"date":"2021-08-31T09:22:10","date_gmt":"2021-08-31T07:22:10","guid":{"rendered":"https:\/\/kinsta.com\/?p=98073"},"modified":"2025-02-07T11:15:02","modified_gmt":"2025-02-07T14:15:02","slug":"componentes-web","status":"publish","type":"post","link":"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/","title":{"rendered":"Uma Introdu\u00e7\u00e3o Completa aos Componentes da Web"},"content":{"rendered":"<p>Todos n\u00f3s temos projetos em que n\u00e3o trabalhar\u00edamos. O c\u00f3digo tornou-se incontrol\u00e1vel, o escopo evoluiu, corre\u00e7\u00f5es r\u00e1pidas aplicadas em cima de outras corre\u00e7\u00f5es, e a estrutura desmoronou sob o seu peso de c\u00f3digo spaghetti. A codifica\u00e7\u00e3o pode ser um neg\u00f3cio desorganizado.<\/p>\n<p>Os projectos beneficiam da utiliza\u00e7\u00e3o de m\u00f3dulos simples e independentes que t\u00eam uma \u00fanica responsabilidade. O c\u00f3digo modular \u00e9 encapsulado, por isso h\u00e1 menos necessidade de se preocupar com a implementa\u00e7\u00e3o. Desde que voc\u00ea saiba o que um m\u00f3dulo ir\u00e1 sair quando lhe for dado um conjunto de entradas, voc\u00ea n\u00e3o precisa necessariamente entender como ele atingiu esse objetivo.<\/p>\n<p>A aplica\u00e7\u00e3o de conceitos modulares a uma \u00fanica <a href=\"https:\/\/kinsta.com\/pt\/blog\/melhor-linguagem-de-programacao\/\">linguagem de programa\u00e7\u00e3o<\/a> \u00e9 simples, mas o desenvolvimento web requer uma mistura diversificada de tecnologias. <a href=\"https:\/\/kinsta.com\/pt\/participacao-mercado-navegadores-desktop\/\">Os navegadores<\/a> analisam <a href=\"https:\/\/kinsta.com\/pt\/blog\/html-vs-html5\/\">HTML<\/a>, CSS e JavaScript para renderizar o conte\u00fado, estilos e funcionalidades da p\u00e1gina.<\/p>\n<p>Eles nem sempre se misturam facilmente porque:<\/p>\n<ul>\n<li>O c\u00f3digo relacionado pode ser dividido entre tr\u00eas ou mais arquivos, e<\/li>\n<li>Estilos globais e objetos JavaScript podem interferir uns com os outros de forma inesperada.<\/li>\n<\/ul>\n<p>Estes problemas somam-se aos encontrados pelos tempos de execu\u00e7\u00e3o do idioma, <a href=\"https:\/\/kinsta.com\/pt\/blog\/bibliotecas-javascript\/\">frameworks<\/a>, bancos de dados e outras depend\u00eancias utilizadas no servidor.<\/p>\n<h3>Confira nosso <a href=\"https:\/\/www.youtube.com\/watch?v=hVxZ-te0kio\">Guia em V\u00eddeo<\/a> sobre Componentes da Web<\/h3>\n<kinsta-video src=\"https:\/\/www.youtube.com\/watch?v=hVxZ-te0kio\"><\/kinsta-video>\n<div><\/div><kinsta-auto-toc heading=\"Table of Contents\" exclude=\"last\" list-style=\"arrow\" selector=\"h2\" count-number=\"-1\"><\/kinsta-auto-toc>\n<h2>O que s\u00e3o componentes da Web?<\/h2>\n<p>Um Componente Web \u00e9 uma forma de criar um bloco de c\u00f3digo de responsabilidade \u00fanica encapsulado que pode ser reutilizado em qualquer p\u00e1gina.<\/p>\n<p>Considere a tag HTML <code><strong>&lt;video<\/strong>&gt;<\/code>. Dado um <a href=\"https:\/\/kinsta.com\/pt\/blog\/o-que-e-uma-url\/\">URL<\/a>, um visualizador pode usar controles como play, pause, mover para tr\u00e1s, mover para frente, e ajustar o volume.<\/p>\n<p>O estilo e a funcionalidade s\u00e3o fornecidos, embora voc\u00ea possa fazer modifica\u00e7\u00f5es usando v\u00e1rios atributos e chamadas API JavaScript. Qualquer n\u00famero de elementos <strong><code>&lt;video&gt;<\/code> <\/strong>pode ser colocado dentro de outras tags, e eles n\u00e3o entram em conflito.<\/p>\n<p>E se voc\u00ea precisar de sua pr\u00f3pria funcionalidade personalizada? Por exemplo, um elemento que mostre o n\u00famero de palavras na p\u00e1gina? N\u00e3o h\u00e1 tag HTML <code><strong>&lt;wordcount&gt;<\/strong><\/code> (ainda).<\/p>\n<p>Frameworks como <a href=\"https:\/\/kinsta.com\/pt\/blog\/bibliotecas-javascript\/#reactjs\">React<\/a> e <a href=\"https:\/\/kinsta.com\/pt\/blog\/vue-js\/\">Vue.js<\/a> permitem que os desenvolvedores criem componentes web onde o conte\u00fado, estilo e funcionalidade podem ser definidos em um \u00fanico arquivo JavaScript. Estes resolvem muitos problemas de programa\u00e7\u00e3o complexos, mas tenha isso em mente:<\/p>\n<ul>\n<li>Voc\u00ea deve aprender como usar essa estrutura e atualizar seu c\u00f3digo \u00e0 medida que ele evolui.<\/li>\n<li>Um componente escrito para uma estrutura raramente \u00e9 compat\u00edvel com outro.<\/li>\n<li>As frameworks sobem e diminuem em popularidade. Voc\u00ea se tornar\u00e1 dependente dos caprichos e prioridades da equipe de desenvolvimento e dos usu\u00e1rios.<\/li>\n<li>Componentes Web padr\u00e3o podem adicionar funcionalidade de navegador, o que \u00e9 dif\u00edcil de conseguir apenas em JavaScript (como o Shadow DOM).<\/li>\n<\/ul>\n<p>Felizmente, os conceitos populares introduzidos em bibliotecas e frameworks costumam se tornar padr\u00f5es na web. Levou algum tempo, mas os componentes da Web j\u00e1 chegaram.<\/p>\n\n<h2>Uma breve hist\u00f3ria dos componentes da Web<\/h2>\n<p>Ap\u00f3s muitas falsas partidas espec\u00edficas de fornecedores, o conceito de componentes Web padr\u00e3o foi introduzido pela primeira vez por <a href=\"https:\/\/fronteers.nl\/congres\/2011\/sessions\/web-components-and-model-driven-views-alex-russell\">Alex Russell na Confer\u00eancia Fronteers em 2011<\/a>. A <a href=\"https:\/\/github.com\/Polymer\/polymer\">biblioteca de pol\u00edmeros<\/a> do Google (um polifill baseado nas propostas atuais) chegou dois anos depois, mas as primeiras implementa\u00e7\u00f5es n\u00e3o apareceram no Chrome e Safari at\u00e9 2016.<\/p>\n<p>Os fornecedores de navegadores demoraram a negociar os detalhes, mas os componentes Web foram adicionados ao Firefox em 2018 e ao Edge em 2020 (quando a Microsoft mudou para o motor Chromium).<\/p>\n<p>Compreensivelmente, poucos desenvolvedores t\u00eam estado dispostos ou capazes de adotar componentes Web, mas finalmente atingimos um bom n\u00edvel de suporte a navegador com APIs est\u00e1veis. Nem tudo \u00e9 perfeito, mas elas s\u00e3o uma alternativa cada vez mais vi\u00e1vel aos componentes baseados em framework.<\/p>\n<p>Mesmo que voc\u00ea ainda n\u00e3o esteja disposto a despejar seu favorito, os componentes da Web s\u00e3o compat\u00edveis com todas as frameworks, e as APIs ser\u00e3o suportadas nos pr\u00f3ximos anos.<\/p>\n<p>Reposit\u00f3rios de componentes Web pr\u00e9-constru\u00eddos est\u00e3o dispon\u00edveis para que todos possam dar uma olhada:<\/p>\n<ul>\n<li><a href=\"https:\/\/www.webcomponents.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">WebComponents.org<\/a><\/li>\n<li><a href=\"https:\/\/component.gallery\/\" target=\"_blank\" rel=\"noopener noreferrer\">The Component Gallery<\/a><\/li>\n<li><a href=\"https:\/\/genericcomponents.netlify.app\/\" target=\"_blank\" rel=\"noopener noreferrer\">generic-components<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/mdn\/web-components-examples\" target=\"_blank\" rel=\"noopener noreferrer\">web-components-examples<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/davatron5000\/awesome-standalones\" target=\"_blank\" rel=\"noopener noreferrer\">awesome-standalones<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/scottaohara\/accessible_components\" target=\"_blank\" rel=\"noopener noreferrer\">accessible_components<\/a><\/li>\n<li><a href=\"https:\/\/kickstand-ui.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">Kickstand UI<\/a><\/li>\n<\/ul>\n<p>&#8230; mas escrever o seu pr\u00f3prio c\u00f3digo \u00e9 mais divertido!<\/p>\n<p>Este tutorial fornece uma introdu\u00e7\u00e3o completa aos Componentes Web escritos sem uma estrutura JavaScript. Voc\u00ea aprender\u00e1 o que eles s\u00e3o e como adapt\u00e1-los para seus projetos web. Voc\u00ea vai precisar de algum conhecimento de <a href=\"https:\/\/kinsta.com\/pt\/blog\/html-vs-html5\/\">HTML5<\/a>, CSS e JavaScript.<\/p>\n<h2>Come\u00e7ando com componentes da Web<\/h2>\n<p>Componentes Web s\u00e3o elementos HTML personalizados tais como <code><b>&lt;hello-world&gt;&lt;\/hello-world&gt;<\/b><\/code>. O nome deve conter um tra\u00e7o para nunca entrar em conflito com os elementos oficialmente suportados na especifica\u00e7\u00e3o HTML.<\/p>\n<p>Deve-se definir uma classe ES2015 para controlar o elemento. Pode ser chamado de qualquer coisa, mas o HelloWorld \u00e9 uma pr\u00e1tica comum. Ele deve estender a <a href=\"https:\/\/developer.mozilla.org\/docs\/Web\/API\/HTMLElement\">interface do HTMLElement<\/a>, que representa as propriedades e m\u00e9todos padr\u00e3o de cada elemento HTML.<\/p>\n<p><strong>Nota: <\/strong><a href=\"https:\/\/kinsta.com\/pt\/blog\/navegadores-mais-seguros\/#3-firefox\">Firefox<\/a> permite estender elementos HTML espec\u00edficos tais como HTMLParagraphElement, HTMLImageElement, ou HTMLButtonElement. Isto n\u00e3o \u00e9 suportado em outros navegadores e n\u00e3o permite que voc\u00ea crie um Shadow DOM.<\/p>\n<p>Para fazer qualquer coisa \u00fatil, a classe requer um m\u00e9todo chamado <strong>connectedCallback() <\/strong>que \u00e9 invocado quando o elemento \u00e9 adicionado a um documento:<\/p>\n<pre><code class=\"language-html\">class HelloWorld extends HTMLElement {\n\n  \/\/ connect component\n  connectedCallback() {\n    this.textContent = 'Hello World!';\n  }\n\n}\n<\/code><\/pre>\n<p>Neste exemplo, o texto do elemento est\u00e1 definido para &#8220;Hello World&#8221;.<\/p>\n<p>A classe deve ser registrada no <a href=\"https:\/\/developer.mozilla.org\/docs\/Web\/API\/CustomElementRegistry\">CustomElementRegistry<\/a> para defini-la como um manipulador para um elemento espec\u00edfico:<\/p>\n<pre><code class=\"language-html\">customElements.define( 'hello-world', HelloWorld );\n<\/code><\/pre>\n<p>O navegador agora associa o elemento <code><b>&lt;hello-world&gt;<\/b><\/code> \u00e0 sua classe <strong>HelloWorld <\/strong>quando o seu JavaScript \u00e9 carregado (por exemplo <code><b>&lt;script type=\"module\" src=\".\/helloworld.js\"&gt;&lt;\/script&gt;<\/b><\/code>).<\/p>\n<p>Agora voc\u00ea tem um elemento personalizado!<\/p>\n<p><iframe class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" title=\"&lt;hello-world&gt; component\" src=\"https:\/\/codepen.io\/craigbuckler\/embed\/preview\/WNpaxPN?default-tabs=js%2Cresult&#038;height=300&#038;host=https%3A%2F%2Fcodepen.io&#038;slug-hash=WNpaxPN#?secret=zQNYBUTDjr\" data-secret=\"zQNYBUTDjr\" scrolling=\"no\" frameborder=\"0\" height=\"300\"><\/iframe><\/p>\n<p><a href=\"https:\/\/codepen.io\/craigbuckler\/pen\/WNpaxPN\">Demonstra\u00e7\u00e3o no CodePen<\/a><\/p>\n<p>Este componente pode ser estilizado no CSS como qualquer outro elemento:<\/p>\n<pre><code class=\"language-css\">hello-world {\n  font-weight: bold;\n  color: red;\n}\n<\/code><\/pre>\n<h3>Adicionando atributos<\/h3>\n<p>Este componente n\u00e3o \u00e9 ben\u00e9fico, uma vez que o mesmo texto \u00e9 emitido independentemente. Como qualquer outro elemento, n\u00f3s podemos adicionar atributos HTML:<\/p>\n<pre><code class=\"language-html\">&lt;hello-world name=\"Craig\"&gt;&lt;\/hello-world&gt;\n<\/code><\/pre>\n<p>Isto pode anular o texto para que &#8220;Hello Craig!&#8221; seja exibido. Para conseguir isso, voc\u00ea pode adicionar uma fun\u00e7\u00e3o <strong>constructor<\/strong><strong>() <\/strong>\u00e0 classe <strong>HelloWorld<\/strong>, que \u00e9 executada quando cada objeto \u00e9 criado. Ele deve:<\/p>\n<ol>\n<li>chamar o m\u00e9todo <strong>super() <\/strong>para inicializar o HTMLElement pai, e<\/li>\n<li>fazer outras inicializa\u00e7\u00f5es. Neste caso, vamos definir a propriedade como <strong>name <\/strong>\u00a0que \u00e9 definido como padr\u00e3o de &#8220;World&#8221;:<\/li>\n<\/ol>\n<pre><code class=\"language-js\">class HelloWorld extends HTMLElement {\n\n  constructor() {\n    super();\n    this.name = 'World';\n  }\n\n  \/\/ more code...\n<\/code><\/pre>\n<p>O seu componente s\u00f3 se preocupa com o atributo <strong>name<\/strong>. Uma propriedade <strong>observedAttributes() <\/strong>est\u00e1tica deve retornar um array de propriedades a observar:<\/p>\n<pre><code class=\"language-js\">\/\/ component attributes\nstatic get observedAttributes() {\n  return ['name'];\n}\n<\/code><\/pre>\n<p>Um m\u00e9todo <strong>attributeChangedCallback() <\/strong>\u00e9 chamado quando um atributo \u00e9 definido no HTML ou alterado usando JavaScript. \u00c9 passado o nome da propriedade, o valor antigo e o novo valor:<\/p>\n<pre><code class=\"language-js\">\/\/ attribute change\nattributeChangedCallback(property, oldValue, newValue) {\n\n  if (oldValue === newValue) return;\n  this[ property ] = newValue;\n\n}\n<\/code><\/pre>\n<p>Neste exemplo, apenas o <strong>nome <\/strong>da propriedade seria atualizado, mas voc\u00ea poderia adicionar propriedades adicionais conforme necess\u00e1rio.<\/p>\n<p>Finalmente, voc\u00ea precisa ajustar a mensagem no m\u00e9todo <strong>connectedCallback()<\/strong>:<\/p>\n<pre><code class=\"language-js\">\/\/ connect component\nconnectedCallback() {\n\n  this.textContent = `Hello ${ this.name }!`;\n\n}\n<\/code><\/pre>\n<p><a href=\"https:\/\/codepen.io\/craigbuckler\/pen\/BaWqLOK\">Demonstra\u00e7\u00e3o no CodePen<\/a><\/p>\n<h3>M\u00e9todos do ciclo de vida<\/h3>\n<p>O navegador chama automaticamente seis m\u00e9todos durante todo o ciclo de vida do estado de Componente Web. A lista completa \u00e9 fornecida aqui, embora voc\u00ea j\u00e1 tenha visto os primeiros quatro nos exemplos acima:<\/p>\n<h4>constructor()<\/h4>\n<p>\u00c9 chamado quando o componente \u00e9 inicializado pela primeira vez. Ele deve chamar <strong>super() <\/strong>e pode definir qualquer padr\u00e3o ou realizar outros processos de pr\u00e9-renderiza\u00e7\u00e3o.<\/p>\n<h4>static observedAttributes()<\/h4>\n<p>Retorna um conjunto de atributos que o navegador ir\u00e1 observar.<\/p>\n<h4>attributeChangedCallback(propertyName, oldValue, newValue)<\/h4>\n<p>Chamado sempre que um atributo observado \u00e9 alterado. Os definidos em HTML s\u00e3o passados imediatamente, mas o JavaScript pode modific\u00e1-los:<\/p>\n<pre><code class=\"language-js\">document.querySelector('hello-world').setAttribute('name', 'Everyone');\n<\/code><\/pre>\n<p>O m\u00e9todo pode precisar acionar uma nova renderiza\u00e7\u00e3o quando isso acontecer.<\/p>\n<h4>connectedCallback()<\/h4>\n<p>Essa fun\u00e7\u00e3o \u00e9 chamada quando o Componente Web \u00e9 anexado a um Modelo de Objeto de Documento. Ele deve executar qualquer renderiza\u00e7\u00e3o necess\u00e1ria.<\/p>\n<h4>disconnectedCallback()<\/h4>\n<p>\u00c9 chamado quando o Componente Web \u00e9 removido de um Modelo de Objeto de Documento. Isso pode ser \u00fatil se voc\u00ea precisar fazer uma limpeza, como remover o estado armazenado ou abortar <a href=\"https:\/\/kinsta.com\/pt\/blog\/admin-ajax\/\">solicita\u00e7\u00f5es Ajax<\/a>.<\/p>\n<h4 id=\"adoptedcallback\" class=\"has-anchor-hash\">adoptedCallback()<\/h4>\n<p>Esta fun\u00e7\u00e3o \u00e9 chamada quando um componente da Web \u00e9 movido de um documento para outro. Voc\u00ea pode encontrar um uso para isso, embora eu tenha lutado para pensar em qualquer caso!<\/p>\n<h2>Como os componentes da web interagem com outros elementos<\/h2>\n<p>Componentes da Web oferece algumas funcionalidades \u00fanicas que voc\u00ea n\u00e3o encontrar\u00e1 em frameworks JavaScript.<\/p>\n<h3>O Shadow DOM<\/h3>\n<p>Embora o Componente Web que constru\u00edmos acima funcione, ele n\u00e3o \u00e9 imune a interfer\u00eancias externas, e o CSS ou JavaScript poderia modific\u00e1-lo. Da mesma forma, os estilos que voc\u00ea define para o seu componente podem vazar e afetar outros.<\/p>\n<p>O Shadow DOM resolve este problema de encapsulamento anexando um DOM separado ao Componente Web:<\/p>\n<pre><code class=\"language-js\">const shadow = this.attachShadow({ mode: 'closed' });\n<\/code><\/pre>\n<p>O modo pode ser qualquer um dos dois:<\/p>\n<ol>\n<li><b>&#8220;open&#8221;<\/b> \u2014 JavaScript na p\u00e1gina externa pode acessar o Shadow DOM (usando <a href=\"https:\/\/developer.mozilla.org\/docs\/Web\/API\/Element\/shadowRoot\">Element.shadowRoot<\/a>), ou<\/li>\n<li><b>&#8220;closed&#8221;<\/b> \u2014 o Shadow DOM s\u00f3 pode ser acessado dentro do Componente Web.<\/li>\n<\/ol>\n<p>O Shadow DOM pode ser manipulado como qualquer outro elemento do DOM:<\/p>\n<pre><code class=\"language-js\">connectedCallback() {\n\n  const shadow = this.attachShadow({ mode: 'closed' });\n\n  shadow.innerHTML = `\n    &lt;style&gt;\n      p {\n        text-align: center;\n        font-weight: normal;\n        padding: 1em;\n        margin: 0 0 2em 0;\n        background-color: #eee;\n        border: 1px solid #666;\n      }\n    &lt;\/style&gt;\n\n    &lt;p&gt;Hello ${ this.name }!&lt;\/p&gt;`;\n\n}\n<\/code><\/pre>\n<p>O componente agora renderiza o texto &#8220;Hello&#8221; dentro de um elemento <code><strong>&lt;p&gt;<\/strong><\/code> e o estiliza. Ele n\u00e3o pode ser modificado por JavaScript ou CSS fora do componente, embora alguns estilos como a <a href=\"https:\/\/kinsta.com\/pt\/blog\/html-fontes\/\">fonte<\/a> e a cor sejam herdados da p\u00e1gina porque n\u00e3o foram explicitamente definidos.<\/p>\n<p><a href=\"https:\/\/codepen.io\/craigbuckler\/pen\/rNyqyJJ\">Demonstra\u00e7\u00e3o no CodePen<\/a><\/p>\n<p>Os estilos definidos para este componente da Web n\u00e3o podem afetar outros par\u00e1grafos da p\u00e1gina ou mesmo outros <code><strong>&lt;hello-world&gt;<\/strong><\/code> componentes.<\/p>\n<p>Note que o CSS <code>:host<\/code> selector pode estilizar o elemento externo <code><strong>&lt;hello-world&gt;<\/strong><\/code> de dentro do Componente Web:<\/p>\n<pre><code class=\"language-css\">:host {\n  transform: rotate(180deg);\n}\n<\/code><\/pre>\n<p>Voc\u00ea tamb\u00e9m pode definir estilos a serem aplicados quando o elemento usa uma classe espec\u00edfica, por exemplo <code><b>&lt;hello-world class=\"rotate90\"&gt;<\/b><\/code>:<\/p>\n<pre><code class=\"language-css\">:host(.rotate90) {\n  transform: rotate(90deg);\n}\n<\/code><\/pre>\n<h3>Modelos HTML<\/h3>\n<p>A defini\u00e7\u00e3o de HTML dentro de um script pode tornar-se impratic\u00e1vel para componentes Web mais complexos. Um template permite-lhe definir um peda\u00e7o de HTML na sua p\u00e1gina que o seu Componente Web pode usar. Isto tem v\u00e1rios benef\u00edcios:<\/p>\n<ol>\n<li>Voc\u00ea pode ajustar o c\u00f3digo HTML sem ter que reescrever as strings dentro do seu JavaScript.<\/li>\n<li>Os componentes podem ser personalizados sem ter que criar classes JavaScript separadas para cada tipo.<\/li>\n<li>\u00c9 mais f\u00e1cil definir HTML em HTML &#8211; e pode ser modificado no servidor ou cliente antes que o componente seja renderizado.<\/li>\n<\/ol>\n<p>Os templates s\u00e3o definidos em um <code><strong>&lt; template&gt;<\/strong><\/code> tag, e \u00e9 pr\u00e1tico atribuir um ID para que voc\u00ea possa referenci\u00e1-lo dentro da classe do componente. Este exemplo tr\u00eas par\u00e1grafos para exibir a mensagem &#8220;Hello&#8221;:<\/p>\n<pre><code class=\"language-html\">&lt;template id=\"hello-world\"&gt;\n\n  &lt;style&gt;\n    p {\n      text-align: center;\n      font-weight: normal;\n      padding: 0.5em;\n      margin: 1px 0;\n      background-color: #eee;\n      border: 1px solid #666;\n    }\n  &lt;\/style&gt;\n\n  &lt;p class=\"hw-text\"&gt;&lt;\/p&gt;\n  &lt;p class=\"hw-text\"&gt;&lt;\/p&gt;\n  &lt;p class=\"hw-text\"&gt;&lt;\/p&gt;\n\n&lt;\/template&gt;\n<\/code><\/pre>\n<p>A classe Web Component pode acessar este modelo, obter seu conte\u00fado e <a href=\"https:\/\/kinsta.com\/pt\/blog\/clonar-facilmente-o-seu-site-wordpress\/\">clonar<\/a> os elementos para garantir que voc\u00ea esteja criando um fragmento \u00fanico de DOM em todos os lugares onde ele \u00e9 usado:<\/p>\n<pre><code class=\"language-js\">const template = document.getElementById('hello-world').content.cloneNode(true);<\/code><\/pre>\n<p>O DOM pode ser modificado e adicionado diretamente ao Shadow DOM:<\/p>\n<pre><code class=\"language-js\">connectedCallback() {\n\n  const\n\n    shadow = this.attachShadow({ mode: 'closed' }),\n    template = document.getElementById('hello-world').content.cloneNode(true),\n    hwMsg = `Hello ${ this.name }`;\n\n  Array.from( template.querySelectorAll('.hw-text') )\n    .forEach( n =&gt; n.textContent = hwMsg );\n\n  shadow.append( template );\n\n}\n<\/code><\/pre>\n<p><a href=\"https:\/\/codepen.io\/craigbuckler\/pen\/QWpZvdQ\">Demonstra\u00e7\u00e3o no CodePen<\/a><\/p>\n<h3>Modelos de slots<\/h3>\n<p>Os slots permitem-lhe personalizar um modelo. Presuma que queria usar o seu <code><strong>&lt;hello-world&gt;<\/strong><\/code> Web Component mas coloque a mensagem dentro de um <strong>&lt;h1&gt; <\/strong>cabe\u00e7alho no Shadow DOM. Voc\u00ea poderia escrever este c\u00f3digo:<\/p>\n<pre><code class=\"language-html\">&lt;hello-world name=\"Craig\"&gt;\n\n  &lt;h1 slot=\"msgtext\"&gt;Hello Default!&lt;\/h1&gt;\n\n&lt;\/hello-world&gt;\n<\/code><\/pre>\n<p>(Note o atributo <strong>slot<\/strong>.)<\/p>\n<p>Opcionalmente, voc\u00ea poderia querer adicionar outros elementos, como um outro par\u00e1grafo:<\/p>\n<pre><code class=\"language-html\">&lt;hello-world name=\"Craig\"&gt;\n\n  &lt;h1 slot=\"msgtext\"&gt;Hello Default!&lt;\/h1&gt;\n  &lt;p&gt;This text will become part of the component.&lt;\/p&gt;\n\n&lt;\/hello-world&gt;\n<\/code><\/pre>\n<p>Os slots podem agora ser implementados dentro do seu template:<\/p>\n<pre><code class=\"language-html\">&lt;template id=\"hello-world\"&gt;\n\n  &lt;slot name=\"msgtext\" class=\"hw-text\"&gt;&lt;\/slot&gt;\n\n  &lt;slot&gt;&lt;\/slot&gt;\n\n&lt;\/template&gt;<\/code><\/pre>\n<p>Um atributo de slot de elemento definido como &#8220;msgtext&#8221; (o <strong><code>&lt;h1&gt;<\/code> <\/strong>) \u00e9 inserido no ponto onde h\u00e1 uma <code><strong>&lt;slot&gt;<\/strong><\/code> chamada &#8220;msgtext&#8221;. O <code><strong>&lt;p&gt;<\/strong><\/code> n\u00e3o tem um nome de slot atribu\u00eddo, mas \u00e9 usado no pr\u00f3ximo dispon\u00edvel sem nome <code><strong>&lt;slot&gt;<\/strong><\/code>. Na verdade, o modelo torna-se:<\/p>\n<pre><code class=\"language-html\">&lt;template id=\"hello-world\"&gt;\n\n  &lt;slot name=\"msgtext\" class=\"hw-text\"&gt;\n    &lt;h1 slot=\"msgtext\"&gt;Hello Default!&lt;\/h1&gt;\n  &lt;\/slot&gt;\n\n  &lt;slot&gt;\n    &lt;p&gt;This text will become part of the component.&lt;\/p&gt;\n  &lt;\/slot&gt;\n\n&lt;\/template&gt;<\/code><\/pre>\n<p>N\u00e3o \u00e9 assim t\u00e3o simples na realidade. Um elemento <code><strong>&lt;slot&gt;<\/strong><\/code> no Shadow DOM <em>aponta <\/em>para os elementos inseridos. Voc\u00ea s\u00f3 pode acess\u00e1-los localizando um <code><strong>&lt;slot&gt;<\/strong><\/code> ent\u00e3o usando o <a href=\"https:\/\/developer.mozilla.org\/docs\/Web\/API\/HTMLSlotElement\/assignedNodes\" target=\"_blank\" rel=\"noopener noreferrer\">assignedNodes() method<\/a> para retornar um array de infantil interno. O m\u00e9todo <strong>connectedCallback() <\/strong>atualizado:<\/p>\n<pre><code class=\"language-js\">connectedCallback() {\n\n  const\n    shadow = this.attachShadow({ mode: 'closed' }),\n    hwMsg = `Hello ${ this.name }`;\n\n  \/\/ append shadow DOM\n  shadow.append(\n    document.getElementById('hello-world').content.cloneNode(true)\n  );\n\n  \/\/ find all slots with a hw-text class\n  Array.from( shadow.querySelectorAll('slot.hw-text') )\n\n    \/\/ update first assignedNode in slot\n    .forEach( n =&gt; n.assignedNodes()[0].textContent = hwMsg );\n\n}\n<\/code><\/pre>\n<p><a href=\"https:\/\/codepen.io\/craigbuckler\/pen\/gOmBBvm\">Demonstra\u00e7\u00e3o no CodePen<\/a><\/p>\n<p>Al\u00e9m disso, n\u00e3o \u00e9 poss\u00edvel estilizar diretamente os elementos inseridos, embora voc\u00ea possa direcionar os slots espec\u00edficos dentro do seu Componente Web:<\/p>\n<pre><code class=\"language-html\">&lt;template id=\"hello-world\"&gt;\n\n  &lt;style&gt;\n    slot[name=\"msgtext\"] { color: green; }\n  &lt;\/style&gt;\n\n  &lt;slot name=\"msgtext\" class=\"hw-text\"&gt;&lt;\/slot&gt;\n  &lt;slot&gt;&lt;\/slot&gt;\n\n&lt;\/template&gt;<\/code><\/pre>\n<p>Os <a href=\"https:\/\/kinsta.com\/pt\/blog\/hierarquia-modelos-wordpress\/\">modelos<\/a> de slots s\u00e3o um pouco incomuns, mas um benef\u00edcio \u00e9 que o seu conte\u00fado ser\u00e1 mostrado se o JavaScript n\u00e3o funcionar. Este c\u00f3digo mostra um t\u00edtulo e par\u00e1grafo padr\u00e3o que s\u00f3 s\u00e3o substitu\u00eddos quando a classe Web Component \u00e9 executada com sucesso:<\/p>\n<pre><code class=\"language-html\">&lt;hello-world name=\"Craig\"&gt;\n\n  &lt;h1 slot=\"msgtext\"&gt;Hello Default!&lt;\/h1&gt;\n  &lt;p&gt;This text will become part of the component.&lt;\/p&gt;\n\n&lt;\/hello-world&gt;\n<\/code><\/pre>\n<p>Portanto, voc\u00ea poderia implementar alguma forma de melhoria progressiva &#8211; mesmo que seja apenas uma mensagem &#8220;Voc\u00ea precisa de JavaScript&#8221;!<\/p>\n<h3>O Shadow DOM Declarativa<\/h3>\n<p>Os exemplos acima constroem um Shadow DOM usando JavaScript. Essa continua sendo a \u00fanica op\u00e7\u00e3o, mas est\u00e1 sendo desenvolvido um Shadow DOM experimental declarativo para o <a href=\"https:\/\/kinsta.com\/pt\/blog\/melhores-extensoes-chrome\/\">Chrome<\/a>. Isto permite a renderiza\u00e7\u00e3o do lado do servidor e evita qualquer mudan\u00e7a de layout ou flashes de conte\u00fado n\u00e3o arquivado.<\/p>\n<p>O seguinte c\u00f3digo \u00e9 detectado pelo analisador de HTML, que cria um Shadow DOM id\u00eantico ao que voc\u00ea criou na \u00faltima se\u00e7\u00e3o (voc\u00ea precisaria atualizar a mensagem conforme necess\u00e1rio):<\/p>\n<pre><code class=\"language-html\">&lt;hello-world name=\"Craig\"&gt;\n\n  &lt;template shadowroot=\"closed\"&gt;\n    &lt;slot name=\"msgtext\" class=\"hw-text\"&gt;&lt;\/slot&gt;\n    &lt;slot&gt;&lt;\/slot&gt;\n  &lt;\/template&gt;\n\n  &lt;h1 slot=\"msgtext\"&gt;Hello Default!&lt;\/h1&gt;\n  &lt;p&gt;This text will become part of the component.&lt;\/p&gt;\n\n&lt;\/hello-world&gt;<\/code><\/pre>\n<p>Esta funcionalidade n\u00e3o est\u00e1 dispon\u00edvel em nenhum browser, e n\u00e3o h\u00e1 garantias de que chegue ao Firefox ou Safari. Voc\u00ea pode <a href=\"https:\/\/web.dev\/declarative-shadow-dom\/\">saber mais sobre o Shadow DOM declarativo<\/a>, e um polifill \u00e9 simples, mas esteja ciente de que a implementa\u00e7\u00e3o pode mudar.<\/p>\n<h3>Eventos Shadow DOM<\/h3>\n<p>O seu Componente Web pode anexar eventos a qualquer elemento do Shadow DOM tal como faria na p\u00e1gina DOM, tal como ouvir eventos de clique em todas as crian\u00e7as internas:<\/p>\n<pre><code class=\"language-js\">shadow.addEventListener('click', e =&gt; {\n\n  \/\/ do something\n\n});\n<\/code><\/pre>\n<p>A menos que voc\u00ea <a href=\"https:\/\/developer.mozilla.org\/docs\/Web\/API\/Event\/stopPropagation\">stopPropagation,<\/a> o evento surgir\u00e1 no DOM da p\u00e1gina, mas ser\u00e1 redirecionado. Isto faz com que pare\u00e7a vir de seu elemento personalizado e n\u00e3o dos elementos que o comp\u00f5em.<\/p>\n<h2>Usando componentes web em outras frameworks<\/h2>\n<p>Qualquer componente da Web que voc\u00ea criar ir\u00e1 funcionar em todas as <a href=\"https:\/\/kinsta.com\/pt\/blog\/bibliotecas-javascript\/#the-most-popular-javascript-frameworks\">frameworks JavaScript<\/a>. Nenhum deles conhece ou se importa com elementos HTML &#8211; seu componente <code><strong>&lt;hello-world&gt;<\/strong><\/code> ser\u00e1 tratado de forma id\u00eantica a um <code><strong>&lt;div&gt;<\/strong><\/code> e colocado no DOM onde a classe ser\u00e1 ativada.<\/p>\n<p><a href=\"https:\/\/custom-elements-everywhere.com\/\">custom-elements-everywhere.com<\/a> fornece uma lista de frameworks e notas de componentes da Web. A maioria \u00e9 totalmente compat\u00edvel, embora o React.js tenha alguns desafios. \u00c9 poss\u00edvel usar <code><strong>&lt;hello-world&gt; <\/strong><\/code>no JSX:<\/p>\n<pre><code class=\"language-js\">import React from 'react';\nimport ReactDOM from 'react-dom';\nimport from '.\/hello-world.js';\n\nfunction MyPage() {\n\n  return (\n    &lt;&gt;\n      &lt;hello-world name=\"Craig\"&gt;&lt;\/hello-world&gt; \n    &lt;\/&gt;\n  );\n\n}\n\nReactDOM.render(&lt;MyPage \/&gt;, document.getElementById('root'));\n<\/code><\/pre>\n<p>&#8230; mas:<\/p>\n<ul>\n<li>Reagir s\u00f3 pode passar tipos de dados primitivos para atributos HTML (n\u00e3o arrays ou objetos)<\/li>\n<li>Reagir n\u00e3o pode ouvir eventos de componentes da Web, por isso voc\u00ea deve anexar manualmente os seus pr\u00f3prios manipuladores.<\/li>\n<\/ul>\n<h2>Cr\u00edticas e problemas dos componentes web<\/h2>\n<p>Os componentes da Web melhoraram significativamente, mas alguns aspectos podem ser complicados de gerir.<\/p>\n<h3>Dificuldades de estiliza\u00e7\u00e3o<\/h3>\n<p>Componentes da Web de Estilo coloca alguns desafios, especialmente se voc\u00ea quiser substituir os estilos scoped. H\u00e1 muitas solu\u00e7\u00f5es:<\/p>\n<ol>\n<li><strong>Evite usar o Shadow DOM. <\/strong>Voc\u00ea pode anexar conte\u00fado diretamente ao seu elemento personalizado, embora qualquer outro JavaScript possa acidental ou maliciosamente alter\u00e1-lo.<\/li>\n<li><strong>Use as classes <\/strong><code><strong>:host<\/strong><\/code>. Como vimos acima, o <a href=\"https:\/\/kinsta.com\/pt\/blog\/caminho-de-renderizacao-critica\/#optimize-css\">CSS escopado<\/a> pode aplicar estilos espec\u00edficos quando uma classe \u00e9 aplicada ao elemento personalizado.<\/li>\n<li><strong>Confira as propriedades (vari\u00e1veis) personalizadas do CSS. <\/strong>Propriedades personalizadas em cascata em Componentes Web, assim, se o seu elemento usa <code><strong>var(--my-color)<\/strong><\/code>, voc\u00ea pode definir &#8211;<strong><code>--my-color<\/code>\u00a0<\/strong>em um recipiente externo (como <code><strong>:root<\/strong><\/code>), e ele ser\u00e1 usado.<\/li>\n<li><strong>Tire proveito das partes do Shadow DOM. <\/strong>O novo <a href=\"https:\/\/developer.mozilla.org\/docs\/Web\/CSS\/::part\">selector::part()<\/a> pode estilizar um componente interno que tem um atributo de pe\u00e7a, ou seja <code><strong>&lt;h1 part=\"heading\"&gt;<\/strong><\/code> dentro de um componente <code><strong>&lt;hello-world&gt;<\/strong><\/code> pode ser estilizado com o selector <code><strong>hello-world::part(heading)<\/strong><\/code>.<\/li>\n<li><strong>Passe em uma string de estilos. <\/strong>Voc\u00ea pode pass\u00e1-los como um atributo para aplicar dentro de um bloco <code><strong>&lt;style&gt;<\/strong><\/code>.<\/li>\n<\/ol>\n<p>Nenhum \u00e9 ideal, e voc\u00ea precisar\u00e1 planejar cuidadosamente como outros usu\u00e1rios podem personalizar o seu componente da Web.<\/p>\n<h3>Entradas ignoradas<\/h3>\n<p>Qualquer <code><b>&lt;input&gt;<\/b><\/code>, <code><b>&lt;textarea&gt;<\/b><\/code>, ou <code><b>&lt;select&gt;<\/b><\/code> em seu Shadow DOM n\u00e3o est\u00e1 automaticamente associado com o formul\u00e1rio que o cont\u00e9m. Os primeiros usu\u00e1rios de componentes da web adicionaram campos ocultos \u00e0 p\u00e1gina DOM ou usaram a <a href=\"https:\/\/developer.mozilla.org\/docs\/Web\/API\/FormData\">interface FormData<\/a> para atualizar valores. Nenhum deles \u00e9 particularmente pr\u00e1tico e quebra o encapsulamento dos componentes da web.<\/p>\n<p>A nova interface ElementInternals permite que um componente web <a href=\"https:\/\/kinsta.com\/pt\/blog\/hooks-wordpress\/\">se conecte a formul\u00e1rios<\/a> a fim de definir valores e validade personalizados. Ele \u00e9 implementado no Chrome, mas um <a href=\"https:\/\/www.npmjs.com\/package\/element-internals-polyfill\">polifilhe est\u00e1 dispon\u00edvel<\/a> para outros navegadores.<\/p>\n<p>Para demonstrar, voc\u00ea vai criar um componente b\u00e1sico <code><strong>&lt;input-age name=\"your-age\"&gt;&lt;\/input-age&gt;<\/strong><\/code>. A classe deve ter um valor est\u00e1tico de <strong>formAssociated <\/strong>value set true e, opcionalmente, um m\u00e9todo <strong>formAssociatedCallback() <\/strong>pode ser chamado quando a forma externa \u00e9 associada:<\/p>\n<pre><code class=\"language-js\">\/\/ &lt;input-age&gt; web component\nclass InputAge extends HTMLElement {\n\n  static formAssociated = true;\n\n  formAssociatedCallback(form) {\n    console.log('form associated:', form.id);\n  }\n<\/code><\/pre>\n<p>O construtor deve agora executar o m\u00e9todo <strong>attachInternals()<\/strong>, que permite ao componente comunicar com o formul\u00e1rio e outro <a href=\"https:\/\/kinsta.com\/pt\/blog\/o-que-e-javascript\/\">c\u00f3digo JavaScript<\/a> que deseja inspecionar o valor ou valida\u00e7\u00e3o:<\/p>\n<pre><code class=\"language-js\">  constructor() {\n\n    super();\n    this.internals = this.attachInternals();\n    this.setValue('');\n\n  }\n\n  \/\/ set form value\n\n  setValue(v) {\n\n    this.value = v;\n\n    this.internals.setFormValue(v);\n\n  }\n<\/code><\/pre>\n<p>O m\u00e9todo ElementInternal <strong>setFormValue() <\/strong>define o valor do elemento para o formul\u00e1rio pai inicializado com uma string vazia aqui (tamb\u00e9m pode ser passado um objeto FormData com m\u00faltiplos pares nome\/valor). Outras propriedades e m\u00e9todos incluem:<\/p>\n<ul>\n<li><b>form<\/b>: o formul\u00e1rio pai<\/li>\n<li><b>labels<\/b>: um conjunto de elementos que rotulam o componente<\/li>\n<li>Op\u00e7\u00f5es de <a href=\"https:\/\/developer.mozilla.org\/docs\/Web\/API\/Constraint_validation\">API de Valida\u00e7\u00e3o de Restri\u00e7\u00f5es<\/a>, tais como willValidate, checkValidity, e validMessage<\/li>\n<\/ul>\n<p>O m\u00e9todo <strong>connectedCallback() <\/strong>cria um Shadow <a href=\"https:\/\/kinsta.com\/pt\/blog\/caminho-de-renderizacao-critica\/#the-dom\">DOM<\/a> como antes, mas tamb\u00e9m deve monitorar o campo para altera\u00e7\u00f5es, assim o <strong>setFormValue() <\/strong>pode ser executado:<\/p>\n<pre><code class=\"language-js\">  connectedCallback() {\n\n    const shadow = this.attachShadow({ mode: 'closed' });\n\n    shadow.innerHTML = `\n      &lt;style&gt;input { width: 4em; }&lt;\/style&gt;\n      &lt;input type=\"number\" placeholder=\"age\" min=\"18\" max=\"120\" \/&gt;`;\n\n    \/\/ monitor input values\n    shadow.querySelector('input').addEventListener('input', e =&gt; {\n      this.setValue(e.target.value);\n    });\n\n  }\n<\/code><\/pre>\n<p>Agora voc\u00ea pode criar um formul\u00e1rio HTML usando este Componente Web que atua de forma similar a outros campos de formul\u00e1rio:<\/p>\n<pre><code class=\"language-html\">&lt;form id=\"myform\"&gt;\n\n  &lt;input type=\"text\" name=\"your-name\" placeholder=\"name\" \/&gt;\n\n  &lt;input-age name=\"your-age\"&gt;&lt;\/input-age&gt;\n\n  &lt;button&gt;submit&lt;\/button&gt;\n\n&lt;\/form&gt;\n<\/code><\/pre>\n<p>Funciona, mas reconhecidamente parece um pouco complicado.<\/p>\n<p>Confira na <a href=\"https:\/\/codepen.io\/craigbuckler\/pen\/JjWmxwo\">demonstra\u00e7\u00e3o no CodePen<\/a><\/p>\n<p>Para mais informa\u00e7\u00f5es, veja este <a href=\"https:\/\/web.dev\/more-capable-form-controls\/\">artigo sobre melhores controles de formul\u00e1rios<\/a>.<\/p>\n\n<h2>Resumo<\/h2>\n<p>Os componentes da Web t\u00eam lutado para ganhar tra\u00e7\u00e3o e ado\u00e7\u00e3o em uma era em que as frameworks JavaScript t\u00eam crescido em estatura e capacidade. Se voc\u00ea vem de React, <a href=\"https:\/\/kinsta.com\/pt\/blog\/bibliotecas-javascript\/#vuejs\"\">Vue<\/a> ou <a href=\"https:\/\/kinsta.com\/pt\/blog\/php-vs-angular\/#what-is-angular\">Angular<\/a>, os componentes da web podem parecer complexos e inc\u00f4modos, especialmente se eles n\u00e3o possuem recursos como a vincula\u00e7\u00e3o de dados e o gerenciamento do estado.<\/p>\n<p>H\u00e1 quest\u00f5es a serem abordadas, mas o futuro dos componentes da web \u00e9 brilhante. Eles s\u00e3o independentes da framework, leves, r\u00e1pidos e podem implementar caracter\u00edsticas que seriam imposs\u00edveis apenas em JavaScript.<\/p>\n<p>H\u00e1 dez anos, poucas pessoas teriam abordado um site sem jQuery, mas os fornecedores de navegadores pegaram as melhores pe\u00e7as e acrescentaram alternativas nativas (como o querySelector). O mesmo ser\u00e1 v\u00e1lido para as frameworks JavaScript, e os componentes web s\u00e3o o primeiro passo provis\u00f3rio.<\/p>\n<p>Voc\u00ea tem perguntas sobre como usar componentes web? Vamos falar sobre isso na se\u00e7\u00e3o de coment\u00e1rios!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Todos n\u00f3s temos projetos em que n\u00e3o trabalhar\u00edamos. O c\u00f3digo tornou-se incontrol\u00e1vel, o escopo evoluiu, corre\u00e7\u00f5es r\u00e1pidas aplicadas em cima de outras corre\u00e7\u00f5es, e a estrutura &#8230;<\/p>\n","protected":false},"author":188,"featured_media":44010,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_kinsta_gated_content":false,"_kinsta_gated_content_redirect":"","footnotes":""},"tags":[130,523],"topic":[1018],"class_list":["post-44006","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","tag-html","tag-javascript","topic-ferramentas-desenvolvimento-web"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v24.6 (Yoast SEO v24.6) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Uma Introdu\u00e7\u00e3o Completa aos Componentes da Web<\/title>\n<meta name=\"description\" content=\"Os componentes Web s\u00e3o uma forma padr\u00e3o de criar elementos HTML reutiliz\u00e1veis e modulares sem utilizar uma estrutura JavaScript.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/\" \/>\n<meta property=\"og:locale\" content=\"pt_PT\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Uma Introdu\u00e7\u00e3o Completa aos Componentes da Web\" \/>\n<meta property=\"og:description\" content=\"Os componentes Web s\u00e3o uma forma padr\u00e3o de criar elementos HTML reutiliz\u00e1veis e modulares sem utilizar uma estrutura JavaScript.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/\" \/>\n<meta property=\"og:site_name\" content=\"Kinsta\u00ae\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/kinstapt\/\" \/>\n<meta property=\"article:published_time\" content=\"2021-08-31T07:22:10+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-02-07T14:15:02+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/08\/web-components-2.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1460\" \/>\n\t<meta property=\"og:image:height\" content=\"730\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Craig Buckler\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:description\" content=\"Os componentes Web s\u00e3o uma forma padr\u00e3o de criar elementos HTML reutiliz\u00e1veis e modulares sem utilizar uma estrutura JavaScript.\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/08\/web-components-2.png\" \/>\n<meta name=\"twitter:creator\" content=\"@craigbuckler\" \/>\n<meta name=\"twitter:site\" content=\"@kinsta_pt\" \/>\n<meta name=\"twitter:label1\" content=\"Escrito por\" \/>\n\t<meta name=\"twitter:data1\" content=\"Craig Buckler\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tempo estimado de leitura\" \/>\n\t<meta name=\"twitter:data2\" content=\"15 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/\"},\"author\":{\"name\":\"Craig Buckler\",\"@id\":\"https:\/\/kinsta.com\/pt\/#\/schema\/person\/715d986404b06691ab3014e06596908e\"},\"headline\":\"Uma Introdu\u00e7\u00e3o Completa aos Componentes da Web\",\"datePublished\":\"2021-08-31T07:22:10+00:00\",\"dateModified\":\"2025-02-07T14:15:02+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/\"},\"wordCount\":3077,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/kinsta.com\/pt\/#organization\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/08\/web-components-2.png\",\"keywords\":[\"html\",\"JavaScript\"],\"inLanguage\":\"pt-PT\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/\",\"url\":\"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/\",\"name\":\"Uma Introdu\u00e7\u00e3o Completa aos Componentes da Web\",\"isPartOf\":{\"@id\":\"https:\/\/kinsta.com\/pt\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/08\/web-components-2.png\",\"datePublished\":\"2021-08-31T07:22:10+00:00\",\"dateModified\":\"2025-02-07T14:15:02+00:00\",\"description\":\"Os componentes Web s\u00e3o uma forma padr\u00e3o de criar elementos HTML reutiliz\u00e1veis e modulares sem utilizar uma estrutura JavaScript.\",\"breadcrumb\":{\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/#breadcrumb\"},\"inLanguage\":\"pt-PT\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-PT\",\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/#primaryimage\",\"url\":\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/08\/web-components-2.png\",\"contentUrl\":\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/08\/web-components-2.png\",\"width\":1460,\"height\":730,\"caption\":\"Uma Introdu\u00e7\u00e3o Completa aos Componentes da Web em 2021\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/kinsta.com\/pt\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Ferramentas de Desenvolvimento Web\",\"item\":\"https:\/\/kinsta.com\/pt\/topicos\/ferramentas-desenvolvimento-web\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Uma Introdu\u00e7\u00e3o Completa aos Componentes da Web\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/kinsta.com\/pt\/#website\",\"url\":\"https:\/\/kinsta.com\/pt\/\",\"name\":\"Kinsta\u00ae\",\"description\":\"Solu\u00e7\u00f5es de hospedagem Premium, r\u00e1pida e segura\",\"publisher\":{\"@id\":\"https:\/\/kinsta.com\/pt\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/kinsta.com\/pt\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"pt-PT\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/kinsta.com\/pt\/#organization\",\"name\":\"Kinsta\",\"url\":\"https:\/\/kinsta.com\/pt\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-PT\",\"@id\":\"https:\/\/kinsta.com\/pt\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/12\/kinsta-logo.jpeg\",\"contentUrl\":\"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/12\/kinsta-logo.jpeg\",\"width\":500,\"height\":500,\"caption\":\"Kinsta\"},\"image\":{\"@id\":\"https:\/\/kinsta.com\/pt\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/kinstapt\/\",\"https:\/\/x.com\/kinsta_pt\",\"https:\/\/www.instagram.com\/kinstahosting\/\",\"https:\/\/www.linkedin.com\/company\/kinsta\/\",\"https:\/\/www.pinterest.com\/kinstahosting\/\",\"https:\/\/www.youtube.com\/c\/Kinsta\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/kinsta.com\/pt\/#\/schema\/person\/715d986404b06691ab3014e06596908e\",\"name\":\"Craig Buckler\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-PT\",\"@id\":\"https:\/\/kinsta.com\/pt\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/8e76011e66720bd2e3e24e164aa6f0b2?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/8e76011e66720bd2e3e24e164aa6f0b2?s=96&d=mm&r=g\",\"caption\":\"Craig Buckler\"},\"description\":\"Freelance UK web developer, writer, and speaker. Has been around a long time and rants about standards and performance.\",\"sameAs\":[\"https:\/\/craigbuckler.com\/\",\"https:\/\/www.linkedin.com\/in\/craigbuckler\",\"https:\/\/x.com\/craigbuckler\",\"https:\/\/www.youtube.com\/channel\/UCQwdl5oBTWGhifS6bRGADMQ\"],\"url\":\"https:\/\/kinsta.com\/pt\/blog\/author\/craigbuckler\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Uma Introdu\u00e7\u00e3o Completa aos Componentes da Web","description":"Os componentes Web s\u00e3o uma forma padr\u00e3o de criar elementos HTML reutiliz\u00e1veis e modulares sem utilizar uma estrutura JavaScript.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/","og_locale":"pt_PT","og_type":"article","og_title":"Uma Introdu\u00e7\u00e3o Completa aos Componentes da Web","og_description":"Os componentes Web s\u00e3o uma forma padr\u00e3o de criar elementos HTML reutiliz\u00e1veis e modulares sem utilizar uma estrutura JavaScript.","og_url":"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/","og_site_name":"Kinsta\u00ae","article_publisher":"https:\/\/www.facebook.com\/kinstapt\/","article_published_time":"2021-08-31T07:22:10+00:00","article_modified_time":"2025-02-07T14:15:02+00:00","og_image":[{"width":1460,"height":730,"url":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/08\/web-components-2.png","type":"image\/png"}],"author":"Craig Buckler","twitter_card":"summary_large_image","twitter_description":"Os componentes Web s\u00e3o uma forma padr\u00e3o de criar elementos HTML reutiliz\u00e1veis e modulares sem utilizar uma estrutura JavaScript.","twitter_image":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/08\/web-components-2.png","twitter_creator":"@craigbuckler","twitter_site":"@kinsta_pt","twitter_misc":{"Escrito por":"Craig Buckler","Tempo estimado de leitura":"15 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/#article","isPartOf":{"@id":"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/"},"author":{"name":"Craig Buckler","@id":"https:\/\/kinsta.com\/pt\/#\/schema\/person\/715d986404b06691ab3014e06596908e"},"headline":"Uma Introdu\u00e7\u00e3o Completa aos Componentes da Web","datePublished":"2021-08-31T07:22:10+00:00","dateModified":"2025-02-07T14:15:02+00:00","mainEntityOfPage":{"@id":"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/"},"wordCount":3077,"commentCount":0,"publisher":{"@id":"https:\/\/kinsta.com\/pt\/#organization"},"image":{"@id":"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/#primaryimage"},"thumbnailUrl":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/08\/web-components-2.png","keywords":["html","JavaScript"],"inLanguage":"pt-PT","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/kinsta.com\/pt\/blog\/componentes-web\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/","url":"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/","name":"Uma Introdu\u00e7\u00e3o Completa aos Componentes da Web","isPartOf":{"@id":"https:\/\/kinsta.com\/pt\/#website"},"primaryImageOfPage":{"@id":"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/#primaryimage"},"image":{"@id":"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/#primaryimage"},"thumbnailUrl":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/08\/web-components-2.png","datePublished":"2021-08-31T07:22:10+00:00","dateModified":"2025-02-07T14:15:02+00:00","description":"Os componentes Web s\u00e3o uma forma padr\u00e3o de criar elementos HTML reutiliz\u00e1veis e modulares sem utilizar uma estrutura JavaScript.","breadcrumb":{"@id":"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/#breadcrumb"},"inLanguage":"pt-PT","potentialAction":[{"@type":"ReadAction","target":["https:\/\/kinsta.com\/pt\/blog\/componentes-web\/"]}]},{"@type":"ImageObject","inLanguage":"pt-PT","@id":"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/#primaryimage","url":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/08\/web-components-2.png","contentUrl":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2021\/08\/web-components-2.png","width":1460,"height":730,"caption":"Uma Introdu\u00e7\u00e3o Completa aos Componentes da Web em 2021"},{"@type":"BreadcrumbList","@id":"https:\/\/kinsta.com\/pt\/blog\/componentes-web\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/kinsta.com\/pt\/"},{"@type":"ListItem","position":2,"name":"Ferramentas de Desenvolvimento Web","item":"https:\/\/kinsta.com\/pt\/topicos\/ferramentas-desenvolvimento-web\/"},{"@type":"ListItem","position":3,"name":"Uma Introdu\u00e7\u00e3o Completa aos Componentes da Web"}]},{"@type":"WebSite","@id":"https:\/\/kinsta.com\/pt\/#website","url":"https:\/\/kinsta.com\/pt\/","name":"Kinsta\u00ae","description":"Solu\u00e7\u00f5es de hospedagem Premium, r\u00e1pida e segura","publisher":{"@id":"https:\/\/kinsta.com\/pt\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/kinsta.com\/pt\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"pt-PT"},{"@type":"Organization","@id":"https:\/\/kinsta.com\/pt\/#organization","name":"Kinsta","url":"https:\/\/kinsta.com\/pt\/","logo":{"@type":"ImageObject","inLanguage":"pt-PT","@id":"https:\/\/kinsta.com\/pt\/#\/schema\/logo\/image\/","url":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/12\/kinsta-logo.jpeg","contentUrl":"https:\/\/kinsta.com\/pt\/wp-content\/uploads\/sites\/3\/2023\/12\/kinsta-logo.jpeg","width":500,"height":500,"caption":"Kinsta"},"image":{"@id":"https:\/\/kinsta.com\/pt\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/kinstapt\/","https:\/\/x.com\/kinsta_pt","https:\/\/www.instagram.com\/kinstahosting\/","https:\/\/www.linkedin.com\/company\/kinsta\/","https:\/\/www.pinterest.com\/kinstahosting\/","https:\/\/www.youtube.com\/c\/Kinsta"]},{"@type":"Person","@id":"https:\/\/kinsta.com\/pt\/#\/schema\/person\/715d986404b06691ab3014e06596908e","name":"Craig Buckler","image":{"@type":"ImageObject","inLanguage":"pt-PT","@id":"https:\/\/kinsta.com\/pt\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/8e76011e66720bd2e3e24e164aa6f0b2?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/8e76011e66720bd2e3e24e164aa6f0b2?s=96&d=mm&r=g","caption":"Craig Buckler"},"description":"Freelance UK web developer, writer, and speaker. Has been around a long time and rants about standards and performance.","sameAs":["https:\/\/craigbuckler.com\/","https:\/\/www.linkedin.com\/in\/craigbuckler","https:\/\/x.com\/craigbuckler","https:\/\/www.youtube.com\/channel\/UCQwdl5oBTWGhifS6bRGADMQ"],"url":"https:\/\/kinsta.com\/pt\/blog\/author\/craigbuckler\/"}]}},"acf":[],"_links":{"self":[{"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/posts\/44006","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/users\/188"}],"replies":[{"embeddable":true,"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/comments?post=44006"}],"version-history":[{"count":16,"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/posts\/44006\/revisions"}],"predecessor-version":[{"id":64724,"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/posts\/44006\/revisions\/64724"}],"alternate":[{"embeddable":true,"hreflang":"en","title":"English","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/44006\/translations\/en"},{"embeddable":true,"hreflang":"fr","title":"French","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/44006\/translations\/fr"},{"embeddable":true,"hreflang":"de","title":"German","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/44006\/translations\/de"},{"embeddable":true,"hreflang":"es","title":"Spanish","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/44006\/translations\/es"},{"embeddable":true,"hreflang":"it","title":"Italian","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/44006\/translations\/it"},{"embeddable":true,"hreflang":"pt","title":"Portuguese","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/44006\/translations\/pt"},{"embeddable":true,"hreflang":"nl","title":"Dutch","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/44006\/translations\/nl"},{"embeddable":true,"hreflang":"sv","title":"Swedish","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/44006\/translations\/se"},{"embeddable":true,"hreflang":"ja","title":"Japanese","href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/44006\/translations\/jp"},{"href":"https:\/\/kinsta.com\/pt\/wp-json\/kinsta\/v1\/posts\/44006\/tree"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/media\/44010"}],"wp:attachment":[{"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/media?parent=44006"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/tags?post=44006"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/kinsta.com\/pt\/wp-json\/wp\/v2\/topic?post=44006"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}