{"id":824,"date":"2019-04-14T19:47:48","date_gmt":"2019-04-15T01:47:48","guid":{"rendered":"https:\/\/www.pensemosweb.com\/?p=824"},"modified":"2024-04-14T16:36:53","modified_gmt":"2024-04-14T22:36:53","slug":"como-crear-un-componente-web-template-y-shadow-dom","status":"publish","type":"post","link":"https:\/\/pensemosweb.com\/en\/como-crear-un-componente-web-template-y-shadow-dom\/","title":{"rendered":"\u00bfC\u00f3mo crear un componente web?  Shadow DOM y etiqueta template"},"content":{"rendered":"<p><strong>\u00bfC\u00f3mo logramos encapsulaci\u00f3n de nuestros nuevos elementos HTML que no provoque conflictos con el resto de una aplicaci\u00f3n?<\/strong>, es decir, que los estilos, HTML interno y JS de un componente web, no colisionen con el resto. <\/p>\n\n\n\n<p>La respuesta b\u00e1sicamente es, el <strong>Shadow DOM<\/strong>. El Shadow DOM nos permite tener los estilos y contenido HTML interno totalmente aislado del exterior. Tambi\u00e9n se ayuda del API del <strong>DOM<\/strong> and <strong>custom elements<\/strong> para establecer comunicaci\u00f3n con otros elementos y componentes internos. Adem\u00e1s con el exterior.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>El amor es de naturaleza interna. No lo vas a encontrar en alguien m\u00e1s, naces con ello, es un componente interno de cada persona. Mira a un beb\u00e9, simplemente es feliz por el hecho de existir. Irradia amor, te lo comparte.<\/p>\n<cite>An\u00f3nimo<\/cite><\/blockquote>\n\n\n\n<p>Antes de comenzar, si a\u00fan no est\u00e1s familiarizado con los <strong>custom elements<\/strong> y los <strong>componentes web<\/strong> nativos en general, te recomiendo revisar primero estas publicaciones:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><a href=\"https:\/\/pensemosweb.com\/en\/como-crear-mejores-aplicaciones-con-los-fascinantes-componentes-web\/\">Componentes web, \u00bfQu\u00e9 son? POO<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/pensemosweb.com\/en\/como-crear-un-componente-web-elementos-html-personalizados\/\">\u00bfC\u00f3mo crear un componente web? Elementos HTML personalizados<\/a><\/li>\n<\/ol>\n\n\n\n<p>Primero vamos a revisar la etiqueta <code>&lt;template&gt;<\/code>, para luego utilizarla dentro de nuestro componente web usando shadow DOM.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u00bfQu\u00e9 es una plantilla?<\/h2>\n\n\n\n<p>Un template o plantilla HTML con el tag <code>&lt;template&gt;<\/code>, es una forma de crear elementos visuales de manera sencilla y eficiente, de tal forma que se pueden definir partes de una p\u00e1gina web o aplicaci\u00f3n a las cuales les podemos insertar valores.<\/p>\n\n\n\n<p>Este template puede ser reutilizado en diferentes vistas de una aplicaci\u00f3n. Tal vez est\u00e9s familiarizado con jade, pug, mustache, o con algunos frameworks y librer\u00edas como angular y vue, los cuales utilizan templates. Tambi\u00e9n si has utilizado wordpress y php, los archivos de los temas serian una especie de templates.<\/p>\n\n\n\n<p>Ahora, los templates que vamos a aprender son espec\u00edficos de HTML  y por lo tanto funcionan en los navegadores web. Para entrar un poco m\u00e1s en contexto veamos un ejemplo sencillo de como podemos crear varios elementos para mostrar un saludo, utilizaremos estas tres fuciones, que forman parte del API del DOM.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>document.createDocumentFragment()<\/code><\/li>\n\n\n\n<li><code>document.createElement('nombreTag', [opciones])<\/code><\/li>\n\n\n\n<li><code>nodo.appendChild(nodo)<\/code><\/li>\n<\/ul>\n\n\n\n<p>Queremos mostrar en nuestra aplicaci\u00f3n un saludo al usuario y lo hacemos de la siguiente forma:<\/p>\n\n\n\n<iframe title=\"Usando document fragment\" src=\"\/\/codepen.io\/jaime_cervantes_ve\/embed\/XQaogr\/?height=265&#038;theme-id=0&#038;default-tab=js,result#full\" frameborder=\"no\" scrolling=\"no\" allowfullscreen=\"allowfullscreen\"><br \/>\n  See the Pen <a href=\"https:\/\/codepen.io\/jaime_cervantes_ve\/pen\/XQaogr\/\">Usando document fragment<\/a> by Jaime Cervantes Velasco<br \/>\n  (<a href=\"https:\/\/codepen.io\/jaime_cervantes_ve\">@jaime_cervantes_ve<\/a>) on <a href=\"https:\/\/codepen.io\">CodePen<\/a>.<br \/><\/iframe>\n\n\n\n<p>Ahora veamos como hacer lo mismo, pero utilizando la etiqueta <code>&lt;template&gt;<\/code>:<\/p>\n\n\n\n<iframe height=\"265\" src=\"\/\/codepen.io\/jaime_cervantes_ve\/embed\/axyPqd\/?height=265&#038;theme-id=0&#038;default-tab=js,result#full\" allowfullscreen=\"true\"><\/iframe>\n\n\n\n<p>Como podemos ver, con la etiqueta <code>&lt;template&gt;<\/code> se usa mucho menos c\u00f3digo, si el contenido de lo que queremos mostrar crece, solo debemos agregar las etiquetas y dem\u00e1s contenido de manera sencilla dentro de la etiqueta <code>&lt;template&gt;<\/code>. Pero si usamos el primer m\u00e9todo, nuestro c\u00f3digo javascript crecer\u00e1 mucho m\u00e1s, esto es m\u00e1s dif\u00edcil de entender y mantener con el tiempo.<\/p>\n\n\n\n<p>La etiqueta template usa internamente un <strong>DocumentFragment<\/strong>, la ventaja de utilizar document fragments es que su contenido no es a\u00fan agregado al \u00e1rbol de nodos, sino que se encuentra en memoria y se inserta una sola vez al final, cuando el contenido esta completo.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#0F111A\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ Agregar document fragment a la p\u00e1ginahost.appendChild(df);\" style=\"color:#babed8;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki material-theme-ocean\" style=\"background-color: #0F111A\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #464B5D; font-style: italic\">\/\/ Agregar document fragment a la p\u00e1gina<\/span><\/span>\n<span class=\"line\"><span style=\"color: #BABED8\">host<\/span><span style=\"color: #89DDFF\">.<\/span><span style=\"color: #82AAFF\">appendChild<\/span><span style=\"color: #BABED8\">(df)<\/span><span style=\"color: #89DDFF\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Existen 4 puntos importantes al utilizar la etiqueta <code>&lt;template&gt;<\/code> para crear plantillas:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The label <code>&lt;template&gt;<\/code> no se pinta en nuestra aplicaci\u00f3n, por default tiene un <code>display: none;<\/code>.<\/li>\n\n\n\n<li>El contenido de la etiqueta <code>&lt;template&gt;<\/code> es un document fragment, el cual tiene la caracter\u00edstica de no estar insertado en el \u00e1rbol de nodos. Esto es bueno para el rendimiento de la aplicaci\u00f3n debido al alto costo de pintar elementos.<\/li>\n\n\n\n<li>El c\u00f3digo JS necesario es muy simple y corto<\/li>\n\n\n\n<li>Cuando clonamos el contenido de nuestro template usando <code>cloneNode()<\/code>, debemos pasar el valor <code>true<\/code> como par\u00e1metro, de otra manera NO clonar\u00edamos los elementos hijos del document fragment de nuestro template.<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"\/wp-content\/uploads\/2019\/04\/template-ejemplo-1024x484.jpg\" alt=\"\" class=\"wp-image-878\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Shadow DOM<\/h2>\n\n\n\n<p>El shadow DOM es un DOM o \u00e1rbol de nodos en las sombras, escondidos de los dem\u00e1s elementos de una aplicaci\u00f3n. Para entender esto vamos a crear nuestro primer componente web utilizando el est\u00e1ndar de <a aria-label=\"custom elements (abre en una nueva pesta\u00f1a)\" rel=\"noreferrer noopener\" href=\"https:\/\/pensemosweb.com\/en\/como-crear-un-componente-web-elementos-html-personalizados\/\" target=\"_blank\">custom elements<\/a>, la etiqueta <code><strong>&lt;template&gt;<\/strong><\/code> y el<strong> shadow DOM<\/strong>.<\/p>\n\n\n\n<p>Nuestro componente se llama <code>mi-saludo<\/code>, con el contenido del ejemplo anterior:<\/p>\n\n\n\n<iframe height=\"300\" style=\"width: 100%;\" scrolling=\"no\" title=\"Custom element, shadow DOM y template. Reutilizaci\u00f3n\" src=\"https:\/\/codepen.io\/jaime_cervantes_ve\/embed\/PgKgLB?defaultTab=html%2Cresult\" frameborder=\"no\" loading=\"lazy\" allowtransparency=\"true\" allowfullscreen=\"true\">\n  See the Pen <a href=\"https:\/\/codepen.io\/jaime_cervantes_ve\/pen\/PgKgLB\">\n  Custom element, shadow DOM y <template> Reutilizaci\u00f3n<\/a> by Jaime Cervantes Velasco (<a href=\"https:\/\/codepen.io\/jaime_cervantes_ve\">@jaime_cervantes_ve<\/a>)\n  on <a href=\"https:\/\/codepen.io\">CodePen<\/a>.\n<\/iframe>\n\n\n\n<p>Si a\u00fan no sabes que son los custom elements, sigue este <a rel=\"noreferrer noopener\" aria-label=\"link (abre en una nueva pesta\u00f1a)\" href=\"https:\/\/pensemosweb.com\/en\/como-crear-un-componente-web-elementos-html-personalizados\/\" target=\"_blank\">link<\/a>. En el ejemplo anterior creamos un custom element llamado <code>mi-saludo<\/code>, dentro del <code>constructor()<\/code> creamos una instancia del template.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#0F111A\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ Obtengo la \u00fanica etiqueta 'template'const tpl = document.querySelector('template');\/\/ Clono su contenido y se crea una instancia del document fragmentconst tplInst = tpl.content.cloneNode(true);\" style=\"color:#babed8;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki material-theme-ocean\" style=\"background-color: #0F111A\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #464B5D; font-style: italic\">\/\/ Obtengo la \u00fanica etiqueta &#39;template&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C792EA\">const<\/span><span style=\"color: #BABED8\"> tpl <\/span><span style=\"color: #89DDFF\">=<\/span><span style=\"color: #BABED8\"> document<\/span><span style=\"color: #89DDFF\">.<\/span><span style=\"color: #82AAFF\">querySelector<\/span><span style=\"color: #BABED8\">(<\/span><span style=\"color: #89DDFF\">&#39;<\/span><span style=\"color: #C3E88D\">template<\/span><span style=\"color: #89DDFF\">&#39;<\/span><span style=\"color: #BABED8\">)<\/span><span style=\"color: #89DDFF\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #464B5D; font-style: italic\">\/\/ Clono su contenido y se crea una instancia del document fragment<\/span><\/span>\n<span class=\"line\"><span style=\"color: #C792EA\">const<\/span><span style=\"color: #BABED8\"> tplInst <\/span><span style=\"color: #89DDFF\">=<\/span><span style=\"color: #BABED8\"> tpl<\/span><span style=\"color: #89DDFF\">.<\/span><span style=\"color: #BABED8\">content<\/span><span style=\"color: #89DDFF\">.<\/span><span style=\"color: #82AAFF\">cloneNode<\/span><span style=\"color: #BABED8\">(<\/span><span style=\"color: #FF9CAC\">true<\/span><span style=\"color: #BABED8\">)<\/span><span style=\"color: #89DDFF\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Luego creamos un shadow DOM y lo adjuntamos al custom element <code>mi-saludo<\/code>:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#0F111A\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ Se crea un nuevi shadow DOM para las instancias de mi-saludothis.attachShadow({ mode: 'open'});\" style=\"color:#babed8;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki material-theme-ocean\" style=\"background-color: #0F111A\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #464B5D; font-style: italic\">\/\/ Se crea un nuevi shadow DOM para las instancias de mi-saludo<\/span><\/span>\n<span class=\"line\"><span style=\"color: #89DDFF\">this.<\/span><span style=\"color: #82AAFF\">attachShadow<\/span><span style=\"color: #BABED8\">(<\/span><span style=\"color: #89DDFF\">{<\/span><span style=\"color: #BABED8\"> <\/span><span style=\"color: #F07178\">mode<\/span><span style=\"color: #89DDFF\">:<\/span><span style=\"color: #BABED8\"> <\/span><span style=\"color: #89DDFF\">&#39;<\/span><span style=\"color: #C3E88D\">open<\/span><span style=\"color: #89DDFF\">&#39;<\/span><span style=\"color: #89DDFF\">}<\/span><span style=\"color: #BABED8\">)<\/span><span style=\"color: #89DDFF\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Y finalmente agregamos el contenido clonado del template dentro del shadow DOM:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#0F111A\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ Y se agrega el template dentro del shadow DOM usando el elemento ra\u00edz 'shadowRoot'this.shadowRoot.appendChild(tplInst);\" style=\"color:#babed8;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki material-theme-ocean\" style=\"background-color: #0F111A\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #464B5D; font-style: italic\">\/\/ Y se agrega el template dentro del shadow DOM usando el elemento ra\u00edz &#39;shadowRoot&#39;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #89DDFF\">this.<\/span><span style=\"color: #BABED8\">shadowRoot<\/span><span style=\"color: #89DDFF\">.<\/span><span style=\"color: #82AAFF\">appendChild<\/span><span style=\"color: #BABED8\">(tplInst)<\/span><span style=\"color: #89DDFF\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>En este \u00faltimo paso usamos la propiedad <code>shadowRoot<\/code>, creada cundo invocamos <code>attachShadow<\/code>, esta propiedad hace referencia a un nodo ra\u00edz especial de donde se empieza a colgar todo lo que definimos dentro de nuestra etiqueta <code>&lt;template&gt;<\/code>, y es a partir de este nodo que agregamos contenido.<\/p>\n\n\n\n<p>Lo que se agrega al shadow DOM esta oculto para el exterior, ning\u00fan <code>document.querySelector()<\/code> externo puede acceder a los elementos del shadow DOM y los estilos definidos en el exterior no pueden acceder a estos elementos ocultos. Esto quiere decir que dentro del shadow DOM podemos utilizar atributos <code>id<\/code> and <code>name<\/code> sin temor a colisionar con los ids y name del exterior.<\/p>\n\n\n\n<p>Cuando creamos un shadow DOM, se hace con la propiedad <code><strong>mode: open<\/strong><\/code>, de esta manera se puede acceder al contenido del shadow DOM usando Javascript y el atributo <code>shadowRoot<\/code>. Sin el atributo shadowRoot es imposible acceder a los elementos y eso nos proporciona encapsulaci\u00f3n a nuestro componente.<\/p>\n\n\n\n<p>Para crear una nueva instancia de nuestro nuevo componente, solo utilizamos el nombre que registramos como etiqueta:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#0F111A\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewbox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"\/\/ Se registra el custom element para poder ser utilizado declarativamente en el HTML o imperativamente mediante JScustomElements.define('mi-saludo', MiSaludo);\" style=\"color:#babed8;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewbox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki material-theme-ocean\" style=\"background-color: #0F111A\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #464B5D; font-style: italic\">\/\/ Se registra el custom element para poder ser utilizado declarativamente en el HTML o imperativamente mediante JS<\/span><\/span>\n<span class=\"line\"><span style=\"color: #BABED8\">customElements<\/span><span style=\"color: #89DDFF\">.<\/span><span style=\"color: #82AAFF\">define<\/span><span style=\"color: #BABED8\">(<\/span><span style=\"color: #89DDFF\">&#39;<\/span><span style=\"color: #C3E88D\">mi-saludo<\/span><span style=\"color: #89DDFF\">&#39;<\/span><span style=\"color: #89DDFF\">,<\/span><span style=\"color: #BABED8\"> MiSaludo)<\/span><span style=\"color: #89DDFF\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Y en el html utilizamos c\u00f3digo declarativo:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;mi-saludo&gt;&lt;\/mi-saludo&gt;<\/code><\/pre>\n\n\n\n<p>\u00bfQu\u00e9 pasa si a nuestro template le agregamos una etiqueta style?  Debido a que las instancias de nuestro template son agregadas al shadow DOM, entonces esos estilos solo afectan dentro del shadow DOM. <\/p>\n\n\n\n<iframe height=\"265\" src=\"\/\/codepen.io\/jaime_cervantes_ve\/embed\/Lvjvqy\/?height=265&#038;theme-id=0&#038;default-tab=js,result#full\" allowfullscreen=\"true\"><\/iframe>\n\n\n\n<p>Para establecer estilos dentro del shadow DOM al nuevo tag creado, se utiliza la pseudoclase <code>:host<\/code>, que hace referencia a la etiqueta hu\u00e9sped del shadow DOM, es decir, <code>mi-saludo<\/code>.<\/p>\n\n\n\n<p>Tambi\u00e9n agregamos en el exterior estilos para las etiquetas <code>&lt;h1&gt;<\/code>, estos estilos no pudieron afectar al contenido interno del shadow DOM,  el \u00fanico <code>h1#mi-id<\/code> con borde rojo es el que se encuentra fuera de nuestro componente. El <code>h1<\/code> externo como el interno tienen el mismo <code>id<\/code>, a causa del encapsulamiento con shadow DOM, no colisionan los estilos con el mismo selector de id.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter\"><img decoding=\"async\" src=\"https:\/\/www.pensemosweb.com\/wp-content\/uploads\/2019\/04\/componente-web-ejemplo-1024x533.jpg\" alt=\"\" class=\"wp-image-901\"\/><\/figure>\n\n\n\n<p>Ahora en nuestro c\u00f3digo html, agreguemos m\u00e1s etiquetas <code>mi-saludo<\/code>:<\/p>\n\n\n\n<iframe height=\"300\" style=\"width: 100%;\" scrolling=\"no\" title=\"Custom element, shadow DOM y template. Reutilizaci\u00f3n\" src=\"https:\/\/codepen.io\/jaime_cervantes_ve\/embed\/PgKgLB?defaultTab=html%2Cresult\" frameborder=\"no\" loading=\"lazy\" allowtransparency=\"true\" allowfullscreen=\"true\">\n  See the Pen <a href=\"https:\/\/codepen.io\/jaime_cervantes_ve\/pen\/PgKgLB\">\n  Custom element, shadow DOM y template. Reutilizaci\u00f3n<\/a> by Jaime Cervantes Velasco (<a href=\"https:\/\/codepen.io\/jaime_cervantes_ve\">@jaime_cervantes_ve<\/a>)\n  on <a href=\"https:\/\/codepen.io\">CodePen<\/a>.\n<\/iframe>\n\n\n\n<p>Como podemos ver la combinaci\u00f3n de estas tres tecnolog\u00edas;  <strong><a rel=\"noreferrer noopener\" href=\"https:\/\/pensemosweb.com\/en\/como-crear-un-componente-web-elementos-html-personalizados\/\" target=\"_blank\">custom elements,<\/a> template y shadow DOM<\/strong> nos permite crear nuevas etiquetas personalizadas con su propio contenido interno sin afectar el exterior y tambi\u00e9n el exterior no puede afectar directamente la implementaci\u00f3n interna de nuestro componente. En el \u00faltimo ejemplo podemos ver como creamos cuatro instancias de nuestro componente simplemente utilizando etiquetas, es decir, reutilizando nuestro componente encapsulado.<\/p>\n\n\n\n<p>En la pr\u00f3xima publicaci\u00f3n veremos como implementar m\u00e1s funcionalidad Javascript encapsulada del componente web y tambi\u00e9n m\u00e1s caracter\u00edsticas muy \u00fatiles del shadow DOM como composici\u00f3n, eventos y m\u00e1s estilos. Finalmente veremos los m\u00f3dulos de JS para completar un componente web reutilizable que pueda ser importado en cualquier otra aplicaci\u00f3n web.<\/p>","protected":false},"excerpt":{"rendered":"<p>\u00bfC\u00f3mo logramos encapsulaci\u00f3n de nuestros nuevos elementos HTML que no provoque conflictos con el resto de una aplicaci\u00f3n?, es decir, que los estilos, HTML interno y JS de un componente web, no colisionen con el resto. La respuesta b\u00e1sicamente es, el Shadow DOM. El Shadow DOM nos permite tener los estilos y contenido HTML interno [&hellip;]<\/p>","protected":false},"author":2,"featured_media":3733,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","footnotes":""},"categories":[24],"tags":[42,54,77],"class_list":["post-824","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-componentes-web","tag-componentes-web","tag-javascript","tag-shadow-dom"],"_links":{"self":[{"href":"https:\/\/pensemosweb.com\/en\/wp-json\/wp\/v2\/posts\/824","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pensemosweb.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pensemosweb.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pensemosweb.com\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/pensemosweb.com\/en\/wp-json\/wp\/v2\/comments?post=824"}],"version-history":[{"count":5,"href":"https:\/\/pensemosweb.com\/en\/wp-json\/wp\/v2\/posts\/824\/revisions"}],"predecessor-version":[{"id":3912,"href":"https:\/\/pensemosweb.com\/en\/wp-json\/wp\/v2\/posts\/824\/revisions\/3912"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/pensemosweb.com\/en\/wp-json\/wp\/v2\/media\/3733"}],"wp:attachment":[{"href":"https:\/\/pensemosweb.com\/en\/wp-json\/wp\/v2\/media?parent=824"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pensemosweb.com\/en\/wp-json\/wp\/v2\/categories?post=824"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pensemosweb.com\/en\/wp-json\/wp\/v2\/tags?post=824"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}