Comenzamos un nuevo capítulo en el que vamos a trabajar de manera más práctica para adaptar una plantilla HTML cualquiera a un proyecto de Qwik.
El objetivo es aplicar los conceptos aprendidos hasta el momento como la gestión de plantillas, reutilización de componentes, enrutamiento y los estilos basándonos en esta plantilla HTML:
https://shorten-up.vercel.app/uPDeBdhmIY
¿Cómo se hace? Para poder hacerlo hay que haber entendido bien los conceptos de los capítulos anteriores, donde hemos estado trabajando con estos conceptos principales:
Una vez que ya tenemos estos conceptos asimilados nos centramos en practicar lo aprendido con algo más real para agruparlos y aplicarlos con ejemplos como el adaptar cualquier plantilla HTML.
En este caso os propongo como práctica hacer la adaptación de una plantilla propia, que he creado con HTML, CSS y Javascript puro.
La plantilla tiene esta apariencia inicial:
Y seguramente os preguntéis, ¿Tan dificil es adaptarlo a Qwik? Dificil no es, cuando ya se han entendido bien los conceptos, pero cuando se están dando los primeros pasos en el framework tampoco es fácil, es cuestión de practicar.
Eso si, después de esta práctica no deberíais de tener ningún problema en hacer este proceso con cualquier plantilla HTML que os encontréis y queráis / necesitéis adaptar.
Para completar este capítulo práctico, vamos a seguir estos pasos durante este capítulo.
Comenzamos con el primer paso del proceso de conversión de una plantilla HTML.
Lo primero que hay que hacer antes de ponerse en marcha es realizar un análisis de la estructura de la plantilla, para identificar que partes son comunes en dicha plantilla.
Identificando estas partes comunes podemos crear el esqueleto principal y aplicar buenas prácticas mediante la reutilización de elementos, cosa que en la plantilla HTML (de este ejemplo y muchos que os encontréis en internet) no se aplica.
Teniendo claro este punto, accedemos a la plantilla y hacemos una visualización rápida de todas las páginas que contiene dicha plantilla.
Tiene tres páginas principales:
Página principal con la información más relevante.
Lista de capítulos del libro, donde se mostrará información extra mediante un elemento accordion
que se suele usar para implementar apartados F.A.Q
(Frecuently Asked Questions o lo que sería Preguntas Frecuentes).
Apartado donde se irán añadiendo proyectos de Qwik implementados.
Una vez que ya tenemos una pequeña noción del objetivo de cada página, empecemos a trabajar con el análisis de que partes son comunes para empezar a crear nuestro elemento layout.tsx
dentro de src/routes
, tal y como hemos aprendido en el capítulo de Layouts (Plantillas).
Comenzamos con la creación del proyecto lo primero.
Mi recomendación es llamar al proyecto 06-practice. Lo importante no es el nombre, es el número que asignamos, para poder identificarlo mejor al capítulo.
Después, debemos de descargarnos el contenido de la plantilla HTML desde aquí:
https://shorten-up.vercel.app/HEQgWB3jQj
Ahora con el proyecto creado y la plantilla descargada es interesante (y diría que necesario) fijarnos en la información de la cabecera y lo que sería la estructura de las diferentes páginas, para ver que elementos tienen en común en lo que respecta a uso de estilos, uso de ficheros de Javascript y demás.
Vamos a por ello.
Inicio
: Página principal.Empezamos por la cabecera de la página, es decir, por el apartado <head>
donde tenemos el siguiente contenido:
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="icon" type="image/x-icon" href="/img/icons/favicon.ico">
<title>Qwik | El Libro</title>
<link rel="stylesheet" href="./styles.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" integrity="sha512-1ycn6IcaQQ40/MKBW2W4Rhis/DbILU74C1vSrLJxCq57o941Ym01SwNsOMqvEBFlcgUa6xLiPY/NS5R+E6ztJQ=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
</head>
Como se puede apreciar, encontramos varios aspectos que seguro que usamos en todas las páginas (si, lo usamos, pero comprobadlo por vuestra cuenta):
styles.css
.favicon
con el fichero favicon.ico
Font Awesome
.viewport
para adaptarlo a diferenes dispositivos.Luego hay aspectos como el título de la página que todas tendrán, pero que en este caso podremos configurar individualmente de manera específica para cada ruta.
Teniendo en cuenta lo siguiente, vamos a copiar el contenido del fichero styles.css
y lo añadimos dentro del fichero src/global.css
, eliminando el contenido actual existente al completo:
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap');
:root {
--primary-color: rgba(21, 25, 52, 1);
--btn-ul-color: #358b94;
--shadow: rgba(0, 0, 0, 0.2);
--hover-btns: rgb(39, 186, 199);
}
...
(Sigue con todo el contenido de styles.css)
Con esto, cuando carguemos nuestra aplicación (npm start
) debería de estar cogiendo estos estilos.
Al iniciar, lo que es la apariencia no se ha modificado nada, por no tener añadidos todavía los elementos asociados a las reglas del CSS aplicado.
Lo importante es ver que si están cogiendo los estilos asignados.
¿Cómo podemos comprobarlo?
Lo podemos realizar mediante las Herramientas del desarrollador
de nuestro navegador favorito.
En Chrome, click derecho sobre cualquier parte de la pantalla y cuando se abren las herramientas de desarrollador
=> Fuentes
=> src/global.css
.
Y de esa manera accedemos al contenido que acabamos de añadir.
Si nos fijamos, también añade las fuentes de Google desde fonts.googleapis.com
:
En este caso cogemos el fichero favicon.ico
que está dentro de img/icons
y lo copiamos en el directorio public
de nuestro proyecto de Qwik:
Por defecto está usando el favicon con extensión svg
.
Podríamos adaptar nuestro favicon
que obtenemos desde la plantilla descargada a esa extensión si quisieramos.
ico
a svg
Existen alternativas para conversiones sencillas de ico a svg como la siguiente donde podremos efectuar la conversión muy fácil:
Lo que tenemos que tener en cuenta para asignar el favicon
correctamente en nuestro proyecto es el apartado donde hacemos referencia a este elemento bien con extensión .ico
o .svg
.
Vamos a src\components\router-head\router-head.tsx
y tenemos el siguiente contenido:
import { component$ } from "@builder.io/qwik";
import { useDocumentHead, useLocation } from "@builder.io/qwik-city";
/**
* The RouterHead component is placed inside of the document `<head>` element.
*/
export const RouterHead = component$(() => {
const head = useDocumentHead();
const loc = useLocation();
return (
<>
<title>{head.title}</title>
<link rel="canonical" href={loc.url.href} />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
{head.meta.map((m) => (
<meta key={m.key} {...m} />
))}
{head.links.map((l) => (
<link key={l.key} {...l} />
))}
{head.styles.map((s) => (
<style key={s.key} {...s.props} dangerouslySetInnerHTML={s.style} />
))}
</>
);
});
Y el apartado que realmente nos interesa para este caso es el correspondiente a la referencia al favicon
:
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
En este caso es la referencia correspondiente al fichero de extensión .svg
.
Si queremos usar el favicon.ico
, aparte de copiarlo en el directorio public
(para poder usarlo a partir de la referencia /
) tenemos que añadir la referencia de la siguiente forma:
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
Aplicando de una manera u otra, el icono que os debe de salir es el siguiente :
El svg sin convertir es el mismo, que es el que viene por defecto, pero si no fuese el mismo, debemos de convertirlo a esta extensión (con el enlace del convertidor que os he proprocionado) en el caso de querer usar en vez de
.ico
Font Awesome
{#html-tpl-configs-fa}Siguiendo en el mismo fichero, añadimos el siguiente código después del apartado del favicon
:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css"
integrity="sha512-1ycn6IcaQQ40/MKBW2W4Rhis/DbILU74C1vSrLJxCq57o941Ym01SwNsOMqvEBFlcgUa6xLiPY/NS5R+E6ztJQ=="
crossorigin="anonymous" referrerpolicy="no-referrer" />
Mostrándonos una pequeña advertencia por no estar adaptadas esas propiedades a Qwik:
Lo que debemos de hacer es modificar de crossorigin
a crossOrigin
y de referrerpolicy
a referrerPolicy
quedando de la siguiente forma:
Guardamos y analizamos en el apartado Fuentes
si está cogiendo la información de esta nueva referencia CSS.
Esto será necesario para adaptar completamente nuestra plantilla y para hacer uso de las fuentes de iconos en los elementos del Footer
:
Y como se puede apreciar, está cogiendo todo correctamente, por lo que pasamos al último paso de este primer apartado de conversión, donde trabajamos con los aspectos globales de configuración.
En la plantilla tenemos esta configuración:
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Y en el proyecto de Qwik (src\components\router-head\router-head.tsx
) por defecto:
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
Como se puede observar, es la misma configuración por lo que no cambiamos nada.
Lo importante es saber que hay que modificarlo en src\components\router-head\router-head.tsx
.
Llegados a este punto empezaremos a trabajar con lo que es el esqueleto del proyecto, donde vamos a analizar las diferentes partes para construir nuestra plantilla en Qwik sin perder su esencia original.
Después de haber añadido las primeras configuraciones globales, vamos a empezar con el proceso de la conversión de este tipo desde HTML, donde realizaremos el análisis de los elementos comunes de la plantilla como pueden ser el elemento de pie de página (Footer
), cabecera (Header
),...
Esto es aplicable para conversiones a otras tecnologías como Angular, React, Vue, etc.
Lo que necesitaremos para llevar a cabo con éxito dicha conversión es conocer bien la tecnología en la que queremos trabajar como destino de la conversión, ya que sin estos conocimientos, será improbable que lo podamos realizar correctamente.
Como en este caso ya tenemos unos conocimientos base sólidos de Qwik, estamos con la suficiente capacidad de poder abordar este objetivo.
Vamos a analizar que elementos existen en las tres páginas.
La apariencia de esta página es la siguiente tal y como hemos visto al inicio del capítulo:
Página inicial, donde entramos inicialmente. Accedemos mediante el fichero index.html
.
Compuesto por un menú superior (1), con varios elementos de menú que da acceso a diferentes páginas.
Este apartado podemos considerarlo como candidato a ser un elemento Core
.
Lo tenemos en cuenta junto con el apartado del Footer
(2) donde se encuentra el Copyright e iconos con las diferentes Redes Sociales y enlaces interesantes.
Por el momento dejamos estos dos elementos como candidatos a elementos Core, ya que suele ser lo común, pero vamos a seguir analizando las diferentes páginas.
Página de los capítulos, donde entramos con el objetivo de poder visualizar los contenidos que encontraremos en el libro. Accedemos mediante el fichero chapters.html
.
En este caso es bastante evidente que también tenemos el menú superior (1) y lo que es el Footer
(2) como elementos comunes y que son candidatos a componentes Core
.
El contenido restante ya es contenido que corresponde únicamente a este apartado.
Página de los proyectos, donde entramos con el objetivo de poder visualizar los proyectos que se han creado en Qwik dentro del libro y con los conocimientos adquiridos en el. Accedemos mediante el fichero projects.html
.
Y como en los dos casos anteriores podemos confirmar que también tenemos el menú superior (1) y lo que es el Footer
(2). Por lo que estos elementos ya los vamos a trabajar a continuación como elementos Core
.
El contenido restante ya es contenido que corresponde únicamente a este apartado aunque hay elementos como el Card
(3) con la información principal de los proyectos que también estaba en el inicio y podríamos reutilizar esa parte de código.
Por el momento, lo dejamos de lado, aunque sin perderle la vista ya que va a ser un componente reutilizable, no a nivel Core, pero si con posibilidad de usarse en más de una ruta.
Header
{#html-tpl-core-comp-header}Comenzamos creando el componente Header
dentro del apartado de nuestro proyecto Qwik src/componentes/core/header.tsx
.
Ahora lo que debemos de hacer es añadir el siguiente código con el objetivo de añadir su estructura:
import { component$ } from '@builder.io/qwik';
export const Header = component$(() => {
return (
<div class='navbar'>
<div class='container flex'>
<h1 class='logo'>
<a class='outline' href='./index.html'>
Qwik | El Libro
</a>
</h1>
<nav>
<ul>
<li class='nav'>
<a class='outline active' href='./index.html'>
Inicio
</a>
</li>
<li class='nav'>
<a class='outline' href='./chapters.html'>
Capítulos
</a>
</li>
<li class='nav'>
<a href='./projects.html' class='outline'>
Proyectos
</a>
</li>
</ul>
</nav>
</div>
</div>
);
});
Vamos a src/routes/layout.tsx
y añadimos el componente, junto con el elemento <Slot />
:
...
import {Header} from './../components/core/header';
export const onGet: RequestHandler = async ({ cacheControl }) => {
...
};
export default component$(() => {
return <>
<Header />
<Slot />
</>;
});
Cuyo resultado al guardar será el siguiente:
Lo que hemos hecho ha sido añadir lo correspondiente al diseño, no se ha implementado correctamente la funcionalidad como puede ser el acceso a las diferentes páginas mediante las diferentes rutas.
Para empezar a implementar las rutas, lo que debemos de hacer es crear dos directorios nuevos dentro de src/routes
con sus correspondientes ficheros index.tsx
:
src/routes/chapters/index.tsx
src/routes/projects/index.tsx
Copiando el mismo contenido que tenemos en src/routes/index.tsx
, haciendo una mínima variación para poder identificar que está cargando una ruta u otra.
src/routes/chapters/index.tsx
:
import { component$ } from "@builder.io/qwik";
import type { DocumentHead } from "@builder.io/qwik-city";
export default component$(() => {
return (
<>
<h1>Hi 👋 - Capítulos</h1>
<p>
Can't wait to see what you build with qwik!
<br />
Happy coding.
</p>
</>
);
});
export const head: DocumentHead = {
title: "Capítulos",
meta: [
{
name: "description",
content: "Listado de capítulos que contiene el libro de Qwik",
},
],
};
src/routes/projects/index.tsx
:
import { component$ } from "@builder.io/qwik";
import type { DocumentHead } from "@builder.io/qwik-city";
export default component$(() => {
return (
<>
<h1>Hi 👋 - Proyectos</h1>
...
</>
);
});
export const head: DocumentHead = {
title: "Proyectos",
meta: [
{
name: "description",
content: "Lista de proyectos desarrollados en Qwik",
},
],
};
Una vez guardados los cambios, probamos a navegar en las 3 rutas existentes, introduciendo a mano las diferentes rutas, que deberían de mostrarnos el contenido de cada uno de los apartados:
Ahora una vez que hemos probado, debemos de ir a src/components/core/header.tsx
y añadir el elemento <Link />
para definir nuestras rutas cargando en forma de SPA, sustituyendo:
<a class='outline' href='<PATH>'>
<LABEL-ETIQUETA>
</a>
Por lo siguiente:
<Link href="/<PATH>" class="outline ">
<LABEL-ETIQUETA>
</Link>
Quedando de la siguiente forma:
import { component$ } from '@builder.io/qwik';
import { Link } from '@builder.io/qwik-city';
export const Header = component$(() => {
return (
<div class='navbar'>
<div class='container flex'>
<h1 class='logo'>
<Link href="/" class="outline">
Qwik | El Libro
</Link>
</h1>
<nav>
<ul>
<li class='nav'>
<Link href="/" class="outline active">
Inicio
</Link>
</li>
<li class='nav'>
<Link href="/chapters" class="outline">
Capítulos
</Link>
</li>
<li class='nav'>
<Link href="/projects" class="outline ">
Proyectos
</Link>
</li>
</ul>
</nav>
</div>
</div>
);
});
En apariencia como se aprecia, se visualiza igual:
Con esto, si hacemos click en los diferentes elementos del menú superior, podemos acceder a sus contenidos como lo haciamos anteriormente introduciendo la ruta a mano, por ejemplo haciendo click en Proyectos
:
Nos muestra los siguiente:
Y aquí vemos que nos redirecciona a /projects
cargando el contenido src/routes/projects/index.tsx
pero estando en esta ruta, no activa la clase active
dinámicamente.
¿Cómo sabes en que ruta nos encontramos para asignarle la clase active
dinámicamente? Necesitamos las dos siguientes referencias:
path
que estamos usando actualmente existe un hook llamado useLocation
.path
, sabemos en todo momento en que ruta nos encontramos.En src/components/core/header.tsx
aplicamos lo siguiente, para saber en todo momento en que ruta nos encontramos:
// 1.- Añadimos el importa del hook a usar
import { useLocation } from '@builder.io/qwik-city';
import { component$ } from '@builder.io/qwik';
import { Link } from '@builder.io/qwik-city';
import { useLocation } from '@builder.io/qwik-city';
export const Header = component$(() => {
// 2.- Asignamos la información de nuestra localización
const location = useLocation();
// 3.- Dentro del link "Qwik | El Libro" añadimos para que nos devuelva el "pathname" principal en el que estamos
return (
<div class='navbar'>
<div class='container flex'>
<h1 class='logo'>
<Link href="/" class="outline">
Qwik | El Libro - {location.url.pathname}
</Link>
</h1>
...
});
Y así resultará:
/
/chapters
/projects
Y con esto, para asignar la clase active
simplemente en cada elemento deberemos de hacer una comparación de la siguiente forma:
...
export const Header = component$(() => {
const location = useLocation();
return (
<div class='navbar'>
<div class='container flex'>
...
<nav>
<ul>
<li class='nav'>
<Link href="/" class={location.url.pathname === '/' ? 'outline active' : 'outline'}>
Inicio
</Link>
</li>
<li class='nav'>
<Link href="/chapters" class={location.url.pathname === '/chapters/' ? 'outline active' : 'outline'}>
Capítulos
</Link>
</li>
<li class='nav'>
<Link href="/projects" class={location.url.pathname === '/projects/' ? 'outline active' : 'outline'}>
Proyectos
</Link>
</li>
</ul>
</nav>
</div>
</div>
);
});
Si guardamos los cambios ya podemos comprobar que el estilo del menú activo funciona correctamente:
/
/chapters
/projects
Bien, llegados a este punto, ya tenemos el primer elemento reutilizable correctamente configurado y en funcionamiento.
Como actividad complementaria podríamos dinamizar los elementos del menú, para reducir código en el componente Header, esto ya os lo dejo para que lo implementéis por vuestra cuenta.
El apartado del Footer
seguiremos el mismo proceso, aunque más sencillo.
Os dejo con lo aprendido a que lo implementéis.
Visualmente, tiene que ser parecido a la plantilla original, algo como esto:
Hay una cosa que tenéis que tener en cuenta es que el año del Copyright, se implementa mediante una función de Javascript, usando la clase Date.
Fijaros en el fichero index.js para adaptarlo al proyecto nuevo de Qwik.
Lo adaptamos obteniendo todo el contenido del elemento footer
dentro de index.html
dejando el componente Footer
la siguiente forma:
import { component$ } from '@builder.io/qwik';
export const Footer = component$(() => {
return (
<footer>
<div class='container grid'>
<div class='copyright'>
<span>Qwik Book</span> - Copyright ©{' '}
<span id='currentYear'>{ new Date().getFullYear()}</span> - Anartz Mugika Ledo
</div>
<div class='profiles'>
<a href='https://twitter.com/mugan86' target='_blank'>
<i class='fab fa-twitter fa-2x'></i>
</a>
<a href='https://www.instagram.com/i.am.anartz/' target='_blank'>
<i class='fab fa-instagram fa-2x'></i>
</a>
<a href='https://www.youtube.com/mugan86' target='_blank'>
<i class='fab fa-youtube fa-2x'></i>
</a>
<a href='https://www.github.com/mugan86' target='_blank'>
<i class='fab fa-github fa-2x'></i>
</a>
<a href='https://mugan86.medium.com/' target='_blank'>
<i class='fab fa-medium fa-2x'></i>
</a>
</div>
</div>
</footer>
);
});
Vamos a src/routes/layout.tsx
y añadimos el componente <Footer />
, junto con el elemento <Slot />
.
Y el resultado visualmente seguirá siendo el mismo solo que ya tenemos la opción de usar ese componente dentro de src/layout.tsx
permitiendo reutilizarlo sin tener que cargarlo una y otra vez cada vez que cargamos una nueva ruta:
Probad las diferentes rutas para poder observar que se mantiene el contenido fijo tanto en el Header
como el Footer
.
Ahora que ya tenemos implementados los dos componentes que componen el Core
de la aplicación, pasamos a añadir los contenidos de todas las páginas de la aplicación.
En este punto lo que vamos a realizar es la adaptación del contenido a las diferentes rutas y lo que haremos únicamente es añadir los contenidos sin añadir la lógica como el desplegar el accordion que encontramos en Capítulos
, ya que para implementarlo en Qwik vamos a necesitar hacerlo mediante la gestión de Estados que veremos en el Capítulo 8.
Al terminar los capítulos correspondientes a la gestión del estado, nos centraremos en esos detalles.
Vamos dentro del directorio que hemos descomprimido y en el index.html
seleccionamos todo el código que se encuentra dentro de body
, lo que NO corrresponde ni al navbar
ni el footer
:
El código sería el siguiente:
...
<section class="showcase">
...
</section>
<div class="container mt-2 mb-5">
...
</div>
...
Y teniendo seleccionado todo, vamos a src/routes/index.tsx
y lo englobamos en el apartado donde añadimos el código JSX:
import { component$ } from "@builder.io/qwik";
import type { DocumentHead } from "@builder.io/qwik-city";
export default component$(() => {
return (
<>
<section class="showcase">
...
</section>
<div class="container mt-2 mb-5">
...
</div>
</>
);
});
export const head: DocumentHead = {
...(SIN CAMBIOS)
};
Al añadir ese código, nos muestra el siguiente error y esto lo que dice básicamente es que hay algún elemento dentro de ese div
que no se ha cerrado correctamente, por lo que lo expandimos y podemos observar que uno de los fallos se encuentra en los input
, que no se encuentran cerrados.
Pasamos de esto donde se ve que los input
no se cierran con />
:
<form action="">
<input type="email" placeholder="Correo electrónico" >
<input type="submit" class="btn" value="Empieza a aprender">
</form>
A cerrar correctamente los input
:
<form action="">
<input type="email" placeholder="Correo electrónico" />
<input type="submit" class="btn" value="Empieza a aprender" />
</form>
Solucionamos el apartado del input
y vemos que el error correspondiente al elemento form
se ha solucionado (1)
:
Y lo que nos quedaría es solucionar lo mismo con los elementos img
que en casi todos los casos se encuentra sin cerrarlo (2)
:
<img src="<path>" alt="" >
Y debería de ser así:
<img src="<path>" alt="" />
Estos errores de cierre los he añadido intencionadamente para que consigamos ver los posibles problemas que nos podemos encontrar en este proceso.
Lo lógico es que encontremos estos elementos bien especificados, pero como en muchos casos vamos a descargar plantillas de Internet, seguramente nos podamos encontrar este tipo de inconvenientes y habiéndolos identificado, no tardaremos nada en poder trabajarlo perfectamente
Guardamos los cambios y podemos observar que en el editor ya no tenemos problemas pero ahora nos dice lo siguiente:
Se ve claro cual es el problema, que no hemos añadido las imágenes en el proyecto:
¿Cómo solucionar este problema?
Debemos de ir al proyecto que hemos descargado antes y debemos de copiar TODO el contenido de dentro del directorio img
en public
dentro de nuestro proyecto Qwik:
Quedando de la siguiente forma, cuando lo copiamos:
A partir ahora, cualquier imagen que vayamos a usar, lo hacemos teniendo en cuenta que especificando el primer caracter (/
), será la referencia que se usará para obtener el recurso desde el directorio public
.
Entonces para acceder y visualizar una imagen que se encuentra en public/img/profile/qwik.webp
en el atributo src
lo añadiríamos con la referencia /img/profile/qwik.webp
especificándose así:
<img src="/img/profile/qwik.webp" alt="" />
Las referencias añadidas en el HTML ya está adaptadas correctamente, pero por si acaso comprobadlo.
Una vez guardado todo, vamos a la página principal y vemos un nuevo "problema", que es una advertencia que se da a partir de la versión 1.2.x de Qwik.
Si hacemos click sobre una de esas advertencias, se solapa una pequeña ventana tipo pop-up con la informacion sobre que ocurre:
Como se puede apreciar, nos está indicando que debemos de añadir los atributos width
y height
especificando sus tamaños, que en este caso especificamos como px
. Cualquier mensaje similar deberemos de añadir esos cambios en todos los elementos.
Cambiamos la imagen principal que se visualiza arriba a lo siguiente, con 192
, que es el valor del tamaño de la imagen que hemos especificado por CSS:
<img src="/img/profile/programmer-girl.webp" width="192" height="192" alt="" />
Al guardar y refrescar, vemos que se ha solucionado, por lo que vuestro trabajo es ir añadiendo esos atributos a los demás elementos de imágenes:
Y después de añadir correctamente los atríbutos a los iconos que tienen la advertencia quedará de la siguiente manera:
Con esto, ya tenemos adaptado la página principal.
Seguramente haya aspectos de temas de diseño responsive y relacionados que hay que afinar, pero eso lo tendréis que trabajar por vuestra cuenta ya que el objetivo es enseñar a adaptar una plantilla HTML que podamos encontrar en la red aplicando las nociones básicas.
Ahora nos centramos en la página de capítulos dejando a mano el fichero chapters.html
del proyecto HTML que hemos descargado.
Aquí como en el paso anterior, donde hemos adaptado la página principal, debemos de copiar contenido que se encuentra dentro del body
. Ignoramos como antes el bloque div
con la clase navbar
y el bloque que corresponde al componente del footer
.
También ignoramos el bloque del elemento section
que tiene la clase projects
que es donde se verían los capítulos.
Por el momento lo dejaremos en blanco, a la espera de trabajar con la gestión de los estados para implementarlo.
Añadimos únicamente el bloque del título dentro de src/routes/chapters/index.tsx
dejando el código con lo siguiente:
import { component$ } from "@builder.io/qwik";
import type { DocumentHead } from "@builder.io/qwik-city";
export default component$(() => {
return (
<>
<div class="container mt-2">
<h1 class="page-title">Listado de capítulos</h1>
<hr />
</div>
</>
);
});
export const head: DocumentHead = {
title: "Capítulos",
meta: [
{
name: "description",
content: "Listado de capítulos que contiene el libro de Qwik",
},
],
};
Guardamos lo que acabamos de añadir y vamos a la ruta /chapters
:
Llegados a este punto, vamos a dar por finalizado esta ruta, a la espera de aprender más sobre lo que es la gestión de estado para poder complementar con la funcionalidad de despliegue de los elementos accordion.
Vamos a adaptar el HTML que corresponde al fichero projects.html
siguiendo el mismo procedimiento anterior en /
y en /chapters
solo que ahora lo hacemos en /projects
(src/routes/projects/index.tsx
).
Tenemos que tener a mano el fichero projects.html
que hemos descargado desde el zip y vamos a añadir el contenido de esa página, teniendo en cuenta de no duplicar el código correspondiente a la cabecera ni al pie de página (Footer
).
Implementamos el siguiente código:
import { component$ } from "@builder.io/qwik";
import type { DocumentHead } from "@builder.io/qwik-city";
export default component$(() => {
return (
<>
<div class="container mt-2"><h1 class="page-title">Proyectos desarrollados en Qwik</h1><hr/></div>
<div class="container mt-2">
<section class="projects">
<div class="container">
<div class="testimonial grid-3">
<div class="card">
<div class="circle">
<img src="/img/profile/men_programmer.webp" alt="">
</div>
<h3>Content Projection</h3>
<p class="text-body">I have learnt web development using this platfrom and I am going to say this is the best platform for
learning. Absolutely
worth the investment!</p>
<button class="btn" onclick="openExternal('https://qwik-slot-content-projection.netlify.app/')">Ver más</button>
</div>
<div class="card">
...
</div>
</div>
</div>
</section>
</div>
</>
);
});
export const head: DocumentHead = {
title: "Proyectos",
meta: [
{
name: "description",
content: "Lista de proyectos desarrollados en Qwik",
},
],
};
Y aquí ocurrirá como en las otras rutas, que aparecerán errores como el de no cerrar el tag de la imagen y también lo que respecta a añadir los tamaños con width
y height
:
<img src="/img/profile/men_programmer.webp" alt="">
Que lo solucionamos dándole un poco de mimo:
<img src="/img/profile/men_programmer.webp" alt="" width="192" height="192"/>
Una vez que solucionamos este problema, tenemos otro, asociado al evento onclick
asociado a una función que nos abre una nueva pestaña para acceder a esa URL.
En Qwik su equivalente directo es onClick$
, lo modificamos y añadimos la funcionalidad para abrir la URL seleccionada en una nueva pestaña con window.open...
.
Pasamos de lo siguiente:
<button class="btn" onclick="openExternal('https://qwik-slot-content-projection.netlify.app/')">Ver más</button>
A esto, cuyo comportamiento no altera y sigue redireccionando a los enlaces especificados:
<button class="btn" onClick$={() => window.open('https://qwik-slot-content-projection.netlify.app/', '_blank')} >Ver más</button>
No olvidéis cambiar los otros enlaces y una vez realizado, guardamos y vemos su funcionamiento, que en este caso sigue siendo el mismo, pero adaptado a Qwik.
onClick$
Trabajaremos más al detalle con este y otros eventos en el capítulo 14: Eventos al detalle.
Ahora lo que necesitamos saber que onClick$ es la traducción en Qwik de lo que es onclick en Javascript.
El resultado como podéis observar es el mismo tanto en lo estético como en el funcionamiento:
Abriendo el proyecto 06-conversion-html-qwik-i podemos encontrar todo el código de lo desarrollado en este capítulo. En el Capítulo 10, ampliaremos con lo pendiente en Capítulos (Chapters)
Lo que hemos trabajado en este capítulo ha sido
El enlace lo tenéis a continuación:
https://shorten-up.vercel.app/Unkwzemdlw
Al finalizar este capítulo, deberíamos de ser capaces de:
public
para mostrar imágenes y recursos públicos dentro de la aplicación.Llegados a este punto, hemos conseguido repasar los conceptos de los capítulos anteriores adaptando un proyecto HTML a Qwik, combinando con nuevos conocimientos como la interpretación de los mensajes de información donde se ha enseñado a como afrontarlos, con el objetivo de solucionarlos.
Como se ha mencionado, algunos apartados se quedan sin adaptar a Qwik, ya que en estos momentos no disponemos de algunos conocimientos que necesitamos, por lo que vamos a seguir con el siguiente capítulo, donde entraremos a trabajar con SSR (Server Side Rendering) de manera más teórica dentro de Qwik.