Como Crear una Página Web con Vue JS 2.6.11 y Vuetify 2.3.10 – Parte 6 (Final)
Demo Github
En la aterior parte llamada Como Crear una Página Web con Vue JS 2.6.11 y Vuetify 2.3.10 – Parte 5, creamos el contenido para la página Servicios, mediante los componentes SobreNosotros y GaleriaServicios. En esta parte 6 y última, vamos a crear el contenido de la página Contacto, con elementos para que los usuarios contacten a la organización, vamos con ello.
Partes
Antes de continuar, te invito a leer los siguientes artículos:
- Que es Vue JS, Historia y otros detalles
- Tu primer Hola Mundo con Vue JS
- 5 Extensiones que te harán más Productivo(a) con Vue JS
- 6 Buenas Prácticas para Desarrolladores Vue JS
- Como Leer un archivo JSON con Vue JS 2.6.11 + Tabla de Bootstrap 4
- Como Crear un Buscador en Tiempo Real con Vue JS 2.6.11 (Buscador de Pokemones) – Parte 1
- Como Leer un EndPoint de API REST que devuelve datos JSON con Vue JS 3 y Axios 0.21.1 – Parte 1
- Puedes ver más en la categoría Vue JS.
Asimismo te invito a escuchar el Podcast: “5 Consejos para ser un Programador más Productivo” (No son los clásicos consejos técnicos de programación, si no de rutinas y buenos hábitos cotidianos)” y “Ventajas y Desventajas de Usar 2 o Más Monitores Para un Desarrollador” (Anchor Podcast):
Spotify: | Sound Cloud: | Apple Podcasts | Anchor Podcasts |
![]() |
![]() |
![]() |
![]() |
Bien ahora continuemos con el Post: Como Crear una Página Web con Vue JS 2.6.11 y Vuetify 2.3.10 – Parte 6 (Final).
Contacto
Igual que con las demás páginas, para mantener un orden voy a crear un directorio llamado Contacto dentro del directorio components, en el colocaré todos los componentes que formarán parte del contenido de la página Contacto.
/pagina-web-vuejs-vuetify ├── .git ├── /node_modules ├── /public ├── /src ├── /assets ├── /components ├── /Contacto // Creo este Directorio ├── /Home ├── /Nosotros ├── /Servicios ├── Footer.vue ├── Home.vue ├── Menu.vue ├── Nosotros.vue ├── Servicios.vue ├── /plugins ├── /router ├── /views ├── App.vue ├── main.js ├── .gitignore ├── babel.config.js ├── package-lock.json ├── package.json ├── README.md ├── vue.config.js ├── yarn.lock
Ahora pasaré a crear el primer elemento de la página Contacto que será un texto de introducción a esta página.
Introduccion a Contacto
Creo un archivo llamado IntroduccionContacto.vue dentro de pagina-web-vuejs-vuetify > src > components > Contacto >IntroduccionContacto.vue
/pagina-web-vuejs-vuetify ├── .git ├── /node_modules ├── /public ├── /src ├── /assets ├── /components ├── /Contacto ├── IntroduccionContacto.vue // Creo este Archivo ├── /Home ├── /Nosotros ├── /Servicios ├── Footer.vue ├── Home.vue ├── Menu.vue ├── Nosotros.vue ├── Servicios.vue ├── /plugins ├── /router ├── /views ├── App.vue ├── main.js ├── .gitignore ├── babel.config.js ├── package-lock.json ├── package.json ├── README.md ├── vue.config.js ├── yarn.lock
Ahora abro el archivo IntroduccionContacto.vue y dentro de las etiquetas <template></template> agrego un v-container y dentro de el coloco un encabezado h1 con el texto Contacto, debajo coloco un texto de introducción a esta página con los medios para contactar a la organización.
<template> <v-container class="mt-10" > <div class="mt-6 mb-3 text-center"> <h1>Contacto</h1> </div> <v-row align="center" justify="center" > <div class="col-md-12"> <p> A continuación todos nuestros medios de contacto. </p> </div> </v-row> </v-container> </template>
A continuación el código completo del archivo IntroduccionContacto.vue
<template> <v-container class="mt-10" > <div class="mt-6 mb-3 text-center"> <h1>Contacto</h1> </div> <v-row align="center" justify="center" > <div class="col-md-12"> <p> A continuación todos nuestros medios de contacto. </p> </div> </v-row> </v-container> </template> <script> export default { name: 'IntroduccionContacto', } </script>
Más adelante, al final de este Post integraré todos los componentes de la página Contacto, pero para tener una idea de como se ve la página hasta ahora, veamos la siguiente imagen.
Bien, ahora pasemos al siguiente componente que contendrá un formulario de contacto, algunos datos de contacto y las redes sociales de la organización.
Formulario, Datos de Contacto y Redes Sociales
Para esta sección voy a colocar 3 columnas, una al lado izquerdo para el formulario de contacto, otra al lado derecho para los datos de contacto y redes sociales y una columna en medio de estas 2 columnas, la cual servirá como divisor de ambas columnas.
Creo un archivo llamado FormularioDatosRedes.vue en pagina-web-vuejs-vuetify > src > components > Contacto > FormularioDatosRedes.vue
/pagina-web-vuejs-vuetify ├── .git ├── /node_modules ├── /public ├── /src ├── /assets ├── /components ├── /Contacto ├── FormularioDatosRedes.vue // Creo este Archivo ├── IntroduccionContacto.vue ├── /Home ├── /Nosotros ├── /Servicios ├── Footer.vue ├── Home.vue ├── Menu.vue ├── Nosotros.vue ├── Servicios.vue ├── /plugins ├── /router ├── /views ├── App.vue ├── main.js ├── .gitignore ├── babel.config.js ├── package-lock.json ├── package.json ├── README.md ├── vue.config.js ├── yarn.lock
Abro el archivo FormularioDatosRedes.vue y dentro de las etiquetas <template></template> coloco al lado izquierdo un formulario de contacto.
<h4 class="ael">Formulario</h4> <validation-observer ref="observer"> <form @submit.prevent="submit"> <validation-provider v-slot="{ errors }" name="Nombre" rules="required|max:50"> <v-text-field v-model="name" :counter="50" :error-messages="errors" label="Nombre"></v-text-field> </validation-provider> <validation-provider v-slot="{ errors }" name="Telefono" :rules="{ required: true, digits: 7 }"> <v-text-field v-model="telefono" :counter="7" :error-messages="errors" label="Telefono"></v-text-field> </validation-provider> <validation-provider v-slot="{ errors }" name="email" rules="required|email"> <v-text-field v-model="email" :error-messages="errors" label="Email"></v-text-field> </validation-provider> <validation-provider v-slot="{ errors }" name="Mensaje" rules="required"> <v-textarea v-model="mensaje" name="input-7-1" :error-messages="errors" label="Mensaje"></v-textarea> </validation-provider> <v-btn class="mr-4 mt-5" type="submit" color="primary"> Aceptar </v-btn> <v-btn class="mt-5" @click="clear" color="secondary"> Limpiar </v-btn> </form> </validation-observer>
Si voy al navegador debería de ver el formulario de contacto que acabo de agregar:
Asimismo dentro del archivo FormularioDatosRedes.vue y dentro de las etiquetas <template></template> coloco al lado derecho los datos de contacto de la organización y debajo sus redes sociales.
<div class="datosdecontacto"> <h4 class="ael pb-2">Datos de Contacto</h4> <div class="ael"> <div class="pb-2"> <v-icon color="black"> mdi-home </v-icon> Av. Lunitas # 333 - Pasales </div> <div class="pb-2"> <v-icon color="black"> mdi-phone </v-icon> 01 444 4444 </div> <div class="pb-2"> <v-icon color="black"> mdi-cellphone </v-icon> 999 999 999 </div> <div class="pb-2"> <v-icon color="black"> mdi-email </v-icon> correo@miproyecto.com </div> </div> </div> <div class="rs mt-7"> <h4 class="ael pb-2">Redes Sociales</h4> <div class="ael"> <ul> <li> <a href="#" title="Facebook"> <v-icon large color="black"> mdi-facebook </v-icon> </a> <a href="#" title="Twitter"> <v-icon large color="black"> mdi-twitter </v-icon> </a> <a href="#" title="Instagram"> <v-icon large color="black"> mdi-instagram </v-icon> </a> <a href="#" title="YouTube"> <v-icon large color="black"> mdi-youtube </v-icon> </a> <a href="#" title="LinkedIn"> <v-icon large color="black"> mdi-linkedin </v-icon> </a> <a href="#" title="Spotify"> <v-icon large color="black"> mdi-spotify </v-icon> </a> <a href="#" title="Discord"> <v-icon large color="black"> mdi-discord </v-icon> </a> </li> </ul> </div> </div>
Igualmente si voy al navegador, debería de ver al lado derecho los datos de contacto y las redes sociales de la organización:
A continuación el código completo del archivo FormularioDatosRedes.vue
<template> <v-container class="mt-10" > <v-row> <div class="col-md-5"> <h4 class="ael">Formulario</h4> <validation-observer ref="observer" > <form @submit.prevent="submit"> <validation-provider v-slot="{ errors }" name="Nombre" rules="required|max:50" > <v-text-field v-model="name" :counter="50" :error-messages="errors" label="Nombre" ></v-text-field> </validation-provider> <validation-provider v-slot="{ errors }" name="Telefono" :rules="{ required: true, digits: 7 }" > <v-text-field v-model="telefono" :counter="7" :error-messages="errors" label="Telefono" ></v-text-field> </validation-provider> <validation-provider v-slot="{ errors }" name="email" rules="required|email" > <v-text-field v-model="email" :error-messages="errors" label="Email" ></v-text-field> </validation-provider> <validation-provider v-slot="{ errors }" name="Mensaje" rules="required" > <v-textarea v-model="mensaje" name="input-7-1" :error-messages="errors" label="Mensaje" ></v-textarea> </validation-provider> <v-btn class="mr-4 mt-5" type="submit" color="primary" > Aceptar </v-btn> <v-btn class="mt-5" @click="clear" color="secondary" > Limpiar </v-btn> </form> </validation-observer> </div> <div class="col-md-2"></div> <div class="col-md-5"> <div class="datosdecontacto"> <h4 class="ael pb-2">Datos de Contacto</h4> <div class="ael"> <div class="pb-2"> <v-icon color="black"> mdi-home </v-icon> Av. Lunitas # 333 - Pasales </div> <div class="pb-2"> <v-icon color="black"> mdi-phone </v-icon> 01 444 4444 </div> <div class="pb-2"> <v-icon color="black"> mdi-cellphone </v-icon> 999 999 999 </div> <div class="pb-2"> <v-icon color="black"> mdi-email </v-icon> correo@miproyecto.com </div> </div> </div> <div class="rs mt-7"> <h4 class="ael pb-2">Redes Sociales</h4> <div class="ael"> <ul> <li> <a href="#" title="Facebook"> <v-icon large color="black"> mdi-facebook </v-icon> </a> <a href="#" title="Twitter"> <v-icon large color="black"> mdi-twitter </v-icon> </a> <a href="#" title="Instagram"> <v-icon large color="black"> mdi-instagram </v-icon> </a> <a href="#" title="YouTube"> <v-icon large color="black"> mdi-youtube </v-icon> </a> <a href="#" title="LinkedIn"> <v-icon large color="black"> mdi-linkedin </v-icon> </a> <a href="#" title="Spotify"> <v-icon large color="black"> mdi-spotify </v-icon> </a> <a href="#" title="Discord"> <v-icon large color="black"> mdi-discord </v-icon> </a> </li> </ul> </div> </div> </div> </v-row> </v-container> </template> <script> import { required, digits, email, max, regex } from 'vee-validate/dist/rules' import { extend, ValidationObserver, ValidationProvider, setInteractionMode } from 'vee-validate' setInteractionMode('eager') extend('digits', { ...digits, message: '{_field_} necesita ser {length} digitos. ({_value_})', }) extend('required', { ...required, message: '{_field_} no puede estar vacío', }) extend('max', { ...max, message: '{_field_} no puede ser mayor que {length} caracteres', }) extend('regex', { ...regex, message: '{_field_} {_value_} no coincide {regex}', }) extend('email', { ...email, message: 'Ingresa un Email válido', }) export default { name: 'SobreNosotros', components: { ValidationProvider, ValidationObserver, }, data: () => ({ nombre: '', telefono: '', email: '', mensaje: '', }), methods: { submit () { this.$refs.observer.validate() }, clear () { this.nombre = '' this.telefono = '' this.email = '' this.mensaje = '' this.$refs.observer.reset() }, }, } </script> <style scoped> .ael { text-align: left !important; } .rs > div > ul > li { display: inline; } .rs > div > ul { padding-left: initial; } </style>
Nota: Para la validación de los campos del formulario, estoy usando VeeValidate, el cual es un framework de validación de formularios basado en plantillas para Vue.js
Bien ahora voy a colocar un mapa que servirá para mostrar la ubicación de la organización.
Mapa
Creo un archivo llamado Mapa.vue dentro de pagina-web-vuejs-vuetify > src > components > Contacto >Mapa.vue
/pagina-web-vuejs-vuetify ├── .git ├── /node_modules ├── /public ├── /src ├── /assets ├── /components ├── /Contacto ├── FormularioDatosRedes.vue ├── IntroduccionContacto.vue ├── Mapa.vue // Creo este Archivo ├── /Home ├── /Nosotros ├── /Servicios ├── Footer.vue ├── Home.vue ├── Menu.vue ├── Nosotros.vue ├── Servicios.vue ├── /plugins ├── /router ├── /views ├── App.vue ├── main.js ├── .gitignore ├── babel.config.js ├── package-lock.json ├── package.json ├── README.md ├── vue.config.js ├── yarn.lock
Abro el archivo Mapa.vue y dentro de las etiquetas <template></template> coloco un elemento iframe con un mapa de google.
<div class="col-md-12"> <iframe src="https://www.google.com/maps/embed?pb=!1m14!1m12!1m3!1d52495.74662436959!2d-77.02157043844453!3d-12.059359678976987!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!5e0!3m2!1ses-419!2spe!4v1651070776624!5m2!1ses-419!2spe" width="100%" height="450" style="border:0;" allowfullscreen="" loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe> </div>
Y si voy al navegador, debería de ver el mapa de google que he agregado:
A continuación el código completo del archivo Mapa.vue
<template> <v-container class="mt-10" > <v-row> <div class="col-md-12"> <iframe src="https://www.google.com/maps/embed?pb=!1m14!1m12!1m3!1d52495.74662436959!2d-77.02157043844453!3d-12.059359678976987!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!5e0!3m2!1ses-419!2spe!4v1651070776624!5m2!1ses-419!2spe" width="100%" height="450" style="border:0;" allowfullscreen="" loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe> </div> </v-row> </v-container> </template> <script> export default { name: 'Mapa', } </script> <style scoped> /* */ </style>
Ok, entonces ya tenemos creado entonces todo el contenido de la página Contacto, pero para que esta página pueda verse bien con todos sus elementos voy a integrar todos sus módulos o componentes, para esto creo un archivo llamado Conctaco.vue en pagina-web-vuejs-vuetify > src > components > Contacto.vue
/pagina-web-vuejs-vuetify ├── .git ├── /node_modules ├── /public ├── /src ├── /assets ├── /components ├── /Contacto ├── /Home ├── /Nosotros ├── /Servicios ├── Contacto.vue // Creo este Archivo ├── Footer.vue ├── Home.vue ├── Menu.vue ├── Nosotros.vue ├── Servicios.vue ├── /plugins ├── /router ├── /views ├── App.vue ├── main.js ├── .gitignore ├── babel.config.js ├── package-lock.json ├── package.json ├── README.md ├── vue.config.js ├── yarn.lock
Ahora abro el archivo Contacto.vue y dentro de las etiquetas <template></template> aparte del Menú y el Footer, agrego los componentes que he creado anteriormente, estos son IntroduccionContacto, FormularioDatosRedes y Mapa
<template> <v-app> <v-main> <Menu /> <IntroduccionContacto /> <FormularioDatosRedes /> <Mapa /> <Newsletter /> <router-view> <v-content> </v-content> </router-view> <Footer /> </v-main> </v-app> </template>
Paso seguido, dentro de las etiquetas <script></script> importo los componentes y defino el título de la página Contacto.
<script> import Menu from './Menu'; import Footer from './Footer'; import IntroduccionContacto from './Contacto/IntroduccionContacto'; import FormularioDatosRedes from './Contacto/FormularioDatosRedes'; import Mapa from './Contacto/Mapa'; import Newsletter from './Home/Newsletter'; export default { name: 'Contacto', watch: { $route: { immediate: true, handler(to) { document.title = to.meta.title || 'Contacto - Mi Proyecto'; } }, }, components: { Menu, Footer, IntroduccionContacto, FormularioDatosRedes, Mapa, Newsletter, }, } </script>
Si ejecutamos el servidor local mediante el siguiente comando.
npm run serve > pagina-web-vuejs-vuetify@0.1.0 serve > vue-cli-service serve INFO Starting development server... ... ... ... (Continua el arranque del servidor) ... ... <s> [webpack.Progress] 95% emitting CopyPlugin <s> [webpack.Progress] 98% after emitting <s> [webpack.Progress] 98% after emitting CopyPlugin DONE Compiled successfully in 17042ms18:46:03 <s> [webpack.Progress] 100% App running at: - Local: http://localhost:8080/ - Network: http://192.168.0.11:8080/ Note that the development build is not optimized. To create a production build, run yarn build.
Y vamos a la ruta local http://localhost:8080/contacto debería de ver la página Contacto con todos sus elementos correspondientes.
Producción
Una ves que ya tengo creado todo el proyecto, voy a pasarlo a producción, es decir compilar los archivos del proyecto y dejarlos listos para subirlos a un servidor.
Primero debo de editar el archivo vue.config.js que se encuentra en el directorio principal del proyecto.
/pagina-web-vuejs-vuetify ├── .git ├── /node_modules ├── /public ├── /src ├── /assets ├── /components ├── /Contacto ├── /Home ├── /Nosotros ├── /Servicios ├── Contacto.vue ├── Footer.vue ├── Home.vue ├── Menu.vue ├── Nosotros.vue ├── Servicios.vue ├── /plugins ├── /router ├── /views ├── App.vue ├── main.js ├── .gitignore ├── babel.config.js ├── package-lock.json ├── package.json ├── README.md ├── vue.config.js // Abro este Archivo ├── yarn.lock
Abro el archivo vue.config.js y en su interior debo de ver el siguiente contenido:
module.exports = { "transpileDependencies": [ "vuetify" ] }
Entonces dentro de module.export agrego la opción publicPath con un valor vacío:
module.exports = { publicPath: '', "transpileDependencies": [ "vuetify" ] }
Grabo el archivo, ahora ya he dejado el proyecto listo para compilarlo.
Para generar o compilar los archivos de mi proyecto, ejecuto el siguiente comando en mi consola de comandos:
npm run build > pagina-web-vuejs-vuetify@0.1.0 build > vue-cli-service build - Building for production... Browserslist: caniuse-lite is outdated. Please run: npx browserslist@latest --update-db Why you should do it regularly: https://github.com/browserslist/browserslist#browsers-data-updating WARNING Compiled with 2 warnings03:16:19 warning asset size limit: The following asset(s) exceed the recommended size limit (244 KiB). This can impact web performance. Assets: css/chunk-vendors.19643457.css (371 KiB) js/chunk-vendors.c1fa10ab.js (334 KiB) warning entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244 KiB). This can impact web performance. Entrypoints: app (736 KiB) css/chunk-vendors.19643457.css js/chunk-vendors.c1fa10ab.js css/app.42decd62.css js/app.40a94877.js File Size Gzipped dist\js\chunk-vendors.c1fa10ab.js 333.54 KiB 107.48 KiB dist\js\app.40a94877.js 30.90 KiB 7.46 KiB dist\js\about.263688ee.js 0.44 KiB 0.31 KiB dist\css\chunk-vendors.19643457.css 371.03 KiB 43.78 KiB dist\css\app.42decd62.css 0.59 KiB 0.35 KiB Images and other types of assets omitted. DONE Build complete. The dist directory is ready to be deployed. INFO Check out deployment instructions at https://cli.vuejs.org/guide/deployment.html
Luego de ejecutar el comando anterior, Vue me creo un directorio con el nombre /dist, en este directorio se encuentran todos los archivos del proyecto, listos para subirlos a mi servidor.
/pagina-web-vuejs-vuetify ├── .git ├── /dist // Este directorio contiene los archivos listos para subirlos a un servidor ├── /node_modules ├── /public ├── /src ├── .gitignore ├── babel.config.js ├── package-lock.json ├── package.json ├── README.md ├── vue.config.js ├── yarn.lock
Los archivos que se encuentran en el directorio /dist los puedes subir a tu servidor mediante un FTP como Filezilla. También existen otras maneras de subir los archivos a un servidor.
Con esto entonces hemos terminado el proyecto, hemos creado una web con Vue y Vuetify, esta web consta de 4 páginas. El aprender a como crear una web con estas tecnologías, te servirá como base para crear páginas web más complejas.
Al inicio de cada Parte del tutorial, he colocado una Demo y en esta sexta y última parte, he colocado el código del proyecto alojado en un repositorio de GitHub.
Nota (s)
- No olvides que debemos usar la Tecnología para hacer cosas Buenas por el Mundo.
Síguenos en nuestras Redes Sociales para que no te pierdas nuestros próximos contenidos.
Social
Redes Sociales (Developers)
Redes Sociales (Digital)