Introducción

En este artículo vamos a echar un ojo a los componentes web, una pieza fundamental de VueJS y del desarrollo frontend a día de hoy.

Bien, si recuerdas, hace tiempo vimos qué es VueJS y cómo instalarlo, pero no vimos cómo empezar a usarlo propiamente dicho. Hoy vamos a aprender cómo se organizan los archivos en Vue y cómo crear tu primer componente web.

Pero antes vamos a ver el concepto de los web components por si todavía no lo controlas.

Qué son los componentes web

Logo componentes web

Los componentes web son un concepto relativamente nuevo, aunque realmente llevas utilizándolos mucho tiempo. Un componente web se trata de un elemento de la página web, con vista, estilos y lógica, que puedes reutilizar a lo largo de tu página web.

Realmente todas las etiquetas html son una especie de componentes web porque se componen también de esas partes.

Por ejemplo al crear un elemento html <input>, realmente estás creando una especie de componente web porque se compone del html que se pinta, los estilos que se pintan por defecto y a lógica de poder escribir.

Pues ahora imagínate que puedes crear tu propio componente con un html mucho más complejo, con más estilos CSS que los de por defecto y con una lógica mucho más compleja. Imagina poder crear un componente web llamado calendario. Simplemente poniendo en la página que lo necesites su etiqueta html, por ejemplo <calendar/> podrías crear un calendario totalmente funcional incluso con la lógica de pasar los meses y los años.

Los componentes no son únicos de Vue, es más, desde hace poco los puedes crear de forma nativa en javascript, pero Vue lo que hace es facilitarnos la tarea de crear los componentes web escribiendo menos código y pudiendo hacer cosas mucho más complejas.

Estructura básica de un proyecto Vue

Antes de empezar a crear componentes web es esencial que sepas la estructura que tiene un proyecto de VueJS para que sepas dónde va cada cosa. Los archivos que muestro a continuación son los que hay nada más crear el proyecto con el comando de Vue create:

Estructura de carpetas de Vue

📁 Carpeta node_modules

Como en todo proyecto javascript que utilice los paquetes NPM, aquí también existe esta carpeta en la que se encuentran todas las dependencias ya instaladas del proyecto. Si no sabes cómo utilizar NPM te recomiendo mi tutorial completo de NPM

📁 Carpeta public

En esta carpeta hay dos archivos:

  • favicon.ico: Es el icono que aparece al lado del nombre de la pestaña en el navegador, por defecto es el logo de Vue pero lo puedes cambiar por tu icono en formato .ico
  • public.html: Es el archivo html sobre el que se montará toda la página. Como hemos dicho en capítulos anteriores, al ser una aplicación SPA, todas las vistas se cargan dinámicamente sin tener que recargar la paǵina. Esto significa que toda la página se incrustará dentro de la etiqueta:

    <div id="app"></div>
    

    Por lo que toda la página compartirá este html. Por cierto, si quieres insertar nuevos archivos de estilos o archivos javascript en el head de esta página NO tienes que llamar a tus archivos aquí, esto lo haremos con webpack.

📁 Carpeta src

En la carpeta src se sitúan los archivos fuentes de nuestra página web. En esta carpeta es dónde se crea todo, es decir, aquí van los componentes y las vistas, así como todo el resto de archivos necesarios para hacerlos funcionar.

  • assets: En esta carpeta se encuentran todos los archivos estáticos de tu aplicación. Cuando creas la estructura se añade el archivo logo.png de ejemplo. Cuando quieras meter una imagen, fuentes, o cosas así lo puedes hacer en esta carpeta. Vue y webpack se encargarán de servir los archivos de esta carpeta para que los puedas llamar desde las vistas.
  • components: Aquí se crearan todos los componentes web. Al crear el proyecto te viene el componente HelloWorld.vue de ejemplo. Lo más recomendable es que dentro de esta carpeta crees carpetas para separar los componentes entre sí. Lo que se suele hacer es separar los componentes por páginas o por área a la que pertenece.
  • views: Si al crear el proyecto has seleccionado manualmente que instale vue router para crear las vistas, aparecerá esta carpeta (si no lo has hecho cuando veamos las vistas te enseñaré como instalarlo en un proyecto ya creado). En esta carpeta se sitúan los componentes encargados de cada una de las vistas y rutas de la página. Lo normal es que haya un componente por cada ruta de la página.

📄 Otros archivos

Aparte de las carpetas que acabamos de ver, Vue crea estos archivos. En mi caso al crear el proyecto de Vue seleccioné que las configuraciones vayan en archivos separados para una mejor gestión.

  • .browserslistrc: En este archivo se especifican cuántas versiones hacia atrás se quiere tener compatibilidad con los nevegadores.
  • .eslintrc.js: Aquí se establecen las normas y las configuraciones del eslint, es decir, de la herramienta que te dice los errores y los warnings cuando guardas los archivos. Si hay una regla que no la quieres, aquí la puedes personalizar o quitar directamente.
  • .gitignore: Aquí le dices al git qué ficheros quiere que ignore. Por defecto Vue te habrá colocado los recomendados.
  • babel.config.js: Configuraciones de babel, la herramienta que transpila el javascript generado a código entendible por navegadores antiguos.
  • package.json y package-lock.json: Donde se establecen las versiones de la librerías requeridas. Además se pueden establecer otros parámetros como el nombre de la aplicación, versión, autores, etc.
  • postcss.config.js: Aquí van las configuraciones del transpilador de CSS, en mi caso uso sass.
  • README.md: Archivo que se muestra al entrar en un proyecto en el github o gitlab. Aquí puedes escribir información sobre el proyecto que creas conveniente.

Hello world. Cómo se crea un componente

Bien, pues ahora que hemos visto todo lo básico para empezar, vamos a ver por fin algo de código. Lo primero que tienes que hacer tras crear un proyecto es ejecutar npm run serve o vue serve para ejecutar vue en modo desarrollo y poder abrir la página que estamos desarrollando.

Si ahora abres localhost:8080en tu navegador verás la página de prueba de Vue con lo que has instalado. Hora de abrir el proyecto en tu editor de texto favorito, en mi caso el vscode.

Como hemos visto, los componentes se crean dentro de src/components, si abres esa carpeta te encontrarás con un archivo llamado HelloWorld.vue, ábrelo. Verás algo como esto:

<template>
<div class="hello">
    <h1></h1>
    <p>
      For a guide and recipes on how to configure / customize this project,<br />
      check out the
      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
    </p>
    <h3>Installed CLI Plugins</h3>
    <ul>
    <li>
        <a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a>
    </li>
    <li>
        <a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a>
    </li>
    </ul>
    <h3>Essential Links</h3>
    <ul>
    <li>
        <a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a>
    </li>
    <li>
        <a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a>
    </li>
    <li>
        <a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a>
    </li>
    <li>
        <a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a>
    </li>
    <li>
        <a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a>
    </li>
    </ul>
    <h3>Ecosystem</h3>
    <ul>
    <li>
        <a href="https://router.vuejs.org" target="_blank" rel="noopener" >vue-router</a>
    </li>
    <li>
        <a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a>
    </li>
    <li>
        <a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener" >vue-devtools</a>
    </li>
    <li>
        <a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a>
    </li>
    <li>
        <a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener" >awesome-vue</a>
    </li>
    </ul>
</div>
</template>

<script>
  export default {
    name: "HelloWorld",
    props: {
      msg: String
    }
  };
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
  h3 {
    margin: 40px 0 0;
  }
  ul {
    list-style-type: none;
    padding: 0;
  }
  li {
    display: inline-block;
    margin: 0 10px;
  }
  a {
    color: #42b983;
  }
</style>

Lo primero, no te asustes. Lo segundo, borra todo el contenido dentro de las etiquetas <template>y déjalo así:

<template>
    <div class="hello">
    Hello world
    </div>
</template>

<script>
  export default {
    name: "HelloWorld",
    props: {
      msg: String
    }
  };
</script>

<style scoped lang="scss">
  h3 {
    margin: 40px 0 0;
  }
  ul {
    list-style-type: none;
    padding: 0;
  }
  li {
    display: inline-block;
    margin: 0 10px;
  }
  a {
    color: #42b983;
  }
</style>

Si ahora abres [localhost:8080](http://localhost:8080) verás que la página ha cambiado y que ahora pone Hello world

Partes que componen un componente en VueJS

Si recuerdas lo que vimos anteriormente, los componentes se componen de 3 partes: la vista, los estilos y la lógica. Vue para diferencias estas 3 partes usa las etiquetas html:

  • Dentro de la etiqueta <template> está el código html del componente. Cada vez que llames al componente, Vue insertará el contenido de esta etiqyeta dentro del DOM de la página web.
  • Dentro de la etiqueta <script> está la lógica del componente. Aquí puedes crear métodos, variables, llamadas al back, etc, es decir, la funcionalidad y el código javascript que está relacionado con el template.
  • Dentro de la etiqueta <style>se encuentran los estilos del componente. Aquí es donde puedes crear estilos css o scss para los elementos que has creado en la etiqueta template.

Los archivos Vue se componen de estas partes en el mismo archivo (Single File Component), a diferencia de Angular que tiene la vista, estilos y lógica de cada componente en archivos separados. Hablemos un poco de cada una de las partes:

La vista

Como hemos dicho aquí puedes escribir los elementos HTML que quieres que tenga el componente cuando lo utilices. Vue cuando renderice el componente y su vista eliminará las etiquetas template y dejará solo su contenido.

Es importante saber que Vue tiene una limitación, no se pueden crear más de un elemento raíz, es decir, este componente no es válido y por tanto salta error:

<template>
  <div class="one"></div>
  <div class="tow"></div>
</template>

Como ves hay dos elementos raíz, los dos div. En cambio este componente si que sería válido:

<template>
  <div class="content">
    <div class="one"></div>
    <div class="tow"></div>
  </div>
</template>

La lógica

Aquí es el lugar en el que escribes la funcionalidad, es decir, el comportamiento del componente. Como veremos más adelante, aquí vas a poder controlar qué ocurre cuando se crea el componente, cuando se destruye, cuando cambia una variable, etc.

Por el momento lo que tienes que saber es que siempre que crees un componente tienes que escribir:

<script>
export default {
  name: "HelloWorld"
};
</script>

Esta es la parte mínima de un componente. En la etiqueta name puedes escribir el nombre del componente, pero siempre en PascalCase (la primera letra en mayúsculas, las palabras juntas y cada una con la primera letra en mayúscula). El campo name no es obligatorio pero viene bien para identificar el componente.

A diferencia de Angular, aquí no tienes que indicar explícitamente que coja la vista de otro archivo.

Creando el componente

Para crear los componentes, lo que yo hago es simplemente crear el fichero con el nombre del componente en PascalCase también (la primera letra en mayúsculas, las palabras juntas y cada una con la primera letra en mayúscula) y creo la estructura básica con todas las partes. Por ejemplo este componente lo crearía dentro de src/components/ con el nombre MiComponente.vue:

<template>
  <p>Mi primer componente en Vue</p>
</template>

<script>
  export default {
    name: "MiComponente"
  }
</script>

<style lang="scss" scoped>
</style>

En la etiqueta style he creado el parámetro lang para poder usar scss pero si quieres usar css básico no hace falta que la pongas (Si creaste el proyecto de Vue de manera manual te habrá preguntado si quieres preprocesadores CSS). También le meto el atributo scoped que sirve para encapsular los estilos.

Al poner scoped, lo que hace Vue es aislar esos estilos para que no afecten a otros componentes de otros archivos, lo que es muy recomendable.

Si dentro de un componente creo un elemento con una clase unos estilos y en otro componente de otro fichero creo la misma clase y le meto otros estilos, los estilos se van a pegar entre sí. Usando scoped tienes la ventaja de poder usar las clases que quieras dentro del componente asegurando que no van a haber conflicto con otros componentes.

Para usar este componente que acabas de crear tienes que hacer lo siguiente. Pongamos que lo quieres insertar en el componente Home de la carpeta /src/views (Si instalaste Vue con el create pero no de la forma manual, o no indicaste que instalara Vue Router puedes importar el componente dentro de App.vue para que veas el ejemplo).

Si abres este componente verás lo siguiente:

<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png" />
      <HelloWorld msg="Welcome to Your Vue.js App" />
    </div>
</template>

<script>
  // @ es un alias a /src
  import HelloWorld from "@/components/HelloWorld.vue";

  export default {
    name: "home",
      components: {
        HelloWorld
    }
  };
</script>

Si te das cuenta ya se está usando el componente HelloWorld. Los componentes siempre se importan encima del export dentro de la etiqueta script.

<script>
  // @ is an alias to /src
  import HelloWorld from "@/components/HelloWorld.vue";
  import MiComponente from "@/components/MiComponente.vue";

  export default {
  ...
  }

Como dice el comentario, al importar, dentro de la ruta se coloca @ como atajo a la carpeta src. Esto es muy recomedable ponerlo.

Ahora toca añadirlo al objeto components de más abajo. Siempre que quieras usar un componente tienes que importarlo y añadirlo aquí, de lo contrario no funcionará.

components: {
  HelloWorld, 
  MiComponente;
}

Por último lo puedes colocar arriba en la vista. Vue por debajo lo que va a hacer es mirar el objeto components que hemos visto antes, y va a sustituir el nombre del componente en PascalCase por el mismo nombre pero en kebab-case. Esto se hace para que cuadren mejor con los elementos HTML. Por lo que solo tenemos que:

<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png" />
    <HelloWorld msg="Welcome to Your Vue.js App" />
    <mi-componente></mi-componente>
  </div>
</template>

Como ves también se pueden usar como PascalCase como el componente de HelloWorld pero es más recomendable en kebab-kase: hello-world

Otro detalle a tener en cuenta es que los componentes los puedes cerrar en la misma etiqueta de apertura:

<mi-componente />

Y listo, ya deberías ver el nuevo componente dentro de la página web. Cada vez que cambies algo de unos de los componentes vas a ver el cambio instantáneamente sin tener que recargar la web.

En conjunto quedaría así:

<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png" />
    <HelloWorld msg="Welcome to Your Vue.js App" />
    <mi-componente />
  </div>
</template>

<script>
  // @ is an alias to /src
  import HelloWorld from "@/components/HelloWorld.vue";
  import MiComponente from "@/components/MiComponente.vue";

  export default {
    name: "home",
    components: {
      HelloWorld,
      MiComponente
    }
  };
</script>

Conclusiones

Pues ya has visto cómo se crean los componentes y cómo se pueden usar. Lógicamente puedes meter componentes dentro de componentes que a su vez tienen más componentes. Cuanto más reutilices los componentes mejor. Si por ejemplo te creas un componente para crear botones, si los usas en toda la web, el día que tengas que cambiarlos solo lo tienes que hacer en un sitio.

En próximos capítulos veremos cómo se pueden personalizar los componentes para que sean flexibles y adaptables a cualquier situación.

Como último consejo para desarrollar con Vue te digo que siempre tengas la consola del navegador abierta. Muchas veces los fallos los detectas porque ha habido un error que se muestra ahí, aunque normalmente los errores te los dice Vue en la propia página.