Cómo hacer más con Vue Router

Vue Router es el enrutador oficial de Vue que se utiliza principalmente para crear múltiples páginas que viven en diferentes rutas ( /home
, /profile
) en su aplicación, pero tiene algunas características que algunas personas no conocen. En este tutorial, aprenderemos sobre algunas características sorprendentes que tiene Vue Router y cómo podemos usarlas en nuestra aplicación.
Vue Router es el enrutador oficial de Vue. Se integra profundamente con el núcleo de Vue para facilitar la creación de aplicaciones de una sola página con Vue. Algunas de sus características populares incluyen:
- Coincidencia de ruta dinámica.
- Rutas nombradas.
- Vistas nombradas.
- Navegación programática.
Estas funciones se utilizan mucho cuando se desarrolla con Vue y esto se debe a que son parte de los conceptos básicos que debe comprender para utilizar el enrutador de manera eficiente. Pero Vue Router tiene algunas características muy útiles que pueden ser muy útiles en el desarrollo y en este artículo las veremos.
A los efectos de este tutorial, crearemos una aplicación sencilla que ayudará a comprender algunos de los conceptos tratados en este artículo. Puedes encontrar todo el código utilizado en este artículo en GitHub . Si está interesado en hacer más con el enrutador, se beneficiará de este tutorial.
Nota: este artículo requiere conocimientos básicos de Vuejs y Vue Router.
Comportamiento de desplazamiento
Este es el comportamiento que se observa al navegar de una página a otra. El comportamiento predeterminado del enrutador Vue solo se nota después de desplazarse a una posición que no es la parte superior de la página. Esto se debe a que, de forma predeterminada, la posición de desplazamiento al salir de una página se mantiene en una página nueva. Lo que esto significa es que, si hace clic en un enlace que conduce a una nueva ruta (es decir, de /home
a /about
) en una posición, digamos, cerca del pie de página de la página actual, la nueva página comenzaría desde esa misma posición en lugar de comenzar. desde la parte superior de la página.
Creé una aplicación Vue usando el comando Vue CLI vue create vue-router-demo
. También seleccioné Vue Router como parte de las opciones mientras configuraba mi aplicación porque la usaremos a lo largo de este tutorial.
También necesitaremos realizar llamadas API a JSONPlaceholder para ilustrar algunos de los conceptos que utilizan el enrutador Vue. Para ello, utilizaremos Axios. Para instalar Axios :
# using YARNyarn add axios# or NPMnpm install axios
Después de instalar Axios, podemos actualizar nuestro Home.vue
para que se vea así:
template div p v-if="loading"Loading..../p ul v-else li v-for="post in posts" :key="post.id" router-link :to="{ name: 'Post', params: { id: post.id, post: post } }" {{ post.title }} /router-link /li /ul /div/templatescript // @ is an alias to /src import axios from "axios"; export default { name: "Home", data() { return { posts: null, loading: false, }; }, mounted() { this.getPosts(); }, methods: { async getPosts() { this.loading = true; try { let res = await axios({ url: "https://jsonplaceholder.typicode.com/posts", method: "GET", }); let posts = res.data; this.posts = posts; this.loading = false; } catch (error) { this.loading = false; } }, }, };/scriptstyle .home { padding: 0 30px; max-width: 800px; margin: 0 auto; } @keyframes blink { from { opacity: 1; } to { opacity: 0; } } .post--empty { height: 250px; margin-top: 30px; animation: blink 0.8s ease-in-out infinite alternate both; display: flex; align-items: center; justify-content: center; font-family: "Lobster", cursive; } ul { text-align: left; } a { color: inherit; }/style
Aquí, lo importamos axios
y lo usamos para obtener una lista de posts
JSONPlaceholder en el getPost
método. También estamos asignando el conjunto de publicaciones obtenidas de esta llamada API a posts
la data
función de esta página, esto se debe a que queremos usar estos datos en nuestra sección de plantilla. Después de esto, recorremos la matriz de publicaciones en una lista ( ul/ul
) y también adjuntamos un enlace a cada publicación usando id
cada publicación como parámetro de enlace (esto se llama coincidencia de ruta dinámica ). También hemos añadido un párrafo que serviría como indicador de carga.
En este punto, así es como se ve esta página:
Lo siguiente sería crear la página que mostrará la información de cada publicación y crear un enlace para ella en el enrutador de nuestra aplicación.
post.vue
template div div h1{{ post.title }}/h1 p v-html="post.body"/p /div pEnd of page/p /div/templatescript export default { name: "Post", props: ["id", "post"], };/scriptstyle .post { padding: 0 30px; height: 110vh; margin: 0 auto; } p { margin: 10px 0; }/style
Aquí, utilizamos accesorios de paso para enrutar componentes a definir id
y post
que pasamos desde la página anterior en forma de parámetros de ruta. Esta es una forma sencilla de acceder a los parámetros de ruta y realizar consultas en lugar de hacer esto:
post.vue
script export default { name: "Post", data() { return { post: this.$route.post, }; }, };/script
Luego utilizamos este post
valor en la sección de plantilla para mostrar el título y el cuerpo de la publicación. Finalmente, agregamos un párrafo al final de la página. También agregamos estilo para la página en la sección de estilo, que incluye la definición height
de 110vh
. Esto se debe a que necesitamos que la página tenga una altura mayor que la altura predeterminada 100vh
para que podamos observar el comportamiento de desplazamiento predeterminado del enrutador.
Lo siguiente sería crear una ruta que mostrara cada publicación. Actualice su index.js
archivo en la carpeta /router (o archivo router.js ) para que se vea así:
import Vue from 'vue'import VueRouter from 'vue-router'import Home from '../views/Home.vue'Vue.use(VueRouter)const routes = [{ path: '/', name: 'Home', component: Home }, { path: '/:id', name: 'Post', props: true, component: () = import ( /* webpackChunkName: "post" */ '../views/Post.vue') }]const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes})export default router
Aquí, definimos una nueva ruta que hace uso de id
lo que se pasaría a esta ruta desde la página de inicio. También estamos desacoplando el parámetro del enrutador (en este caso, post
y id
) usando accesorios.
La parte superior de esta página se ve así:
Si hacemos clic en cualquiera de las publicaciones en la página de inicio que no requiere que nos desplacemos, no notaremos ningún comportamiento extraño en cuanto al desplazamiento, pero si nos desplazamos un poco hacia abajo y hacemos clic en la última publicación de esta lista, esto debería ser la posición en la /post
que aterrizaría la página:
Esto es malo para UX y se debe a que el usuario no espera este comportamiento y es posible que deba comenzar desde la parte superior de una página para obtener la información completa en dicha página.
Vue Router viene con la opción de personalizar este comportamiento según las preferencias individuales; un ejemplo sería guardar la posición de desplazamiento de una ruta anterior al intentar avanzar o retroceder. Para solucionar el problema actual en nuestra aplicación, actualizaríamos nuestro archivo de enrutador para incluir lo siguiente:
import Vue from 'vue'import VueRouter from 'vue-router'import Home from '../views/Home.vue'Vue.use(VueRouter)const routes = [...]const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes, //add this scrollBehavior(to, from, savedPosition) { return { x: 0, y: 0 } }})export default router
Ahora, si nos desplazamos hasta la parte inferior de la página de inicio y hacemos clic en la última publicación, deberías notar que ahora comienza desde la parte superior de la página.
Obtención de datos
Al obtener datos de una API, llamamos al método en el enlace del ciclo de vida mounted
o created
al método, estos son, con diferencia, los métodos más populares que la gente usa cuando desarrolla en Vue. El enrutador Vue viene con otro método en el que realizamos esta solicitud de API antes de navegar a una nueva ruta al realizar esta solicitud utilizando la beforeRouterEnter
protección en dicho componente. A continuación se muestra un ejemplo de cómo recuperar datos de JSONPlaceholder usando este método:
beforeRouteEnter(to, from, next) { axios .get("https://jsonplaceholder.typicode.com/posts") .then((res) = { next((vm) = vm.fetchData(res)); }) .catch((err) = { console.error(err); });},methods: { fetchData(res) { let post = res.data; this.posts = post; }, },
Aquí, obtenemos una lista de publicaciones de una API usando Axios y cuando se completa esta solicitud, llamamos next
. En este punto del ciclo de vida de este componente, this
no está disponible porque el componente no se ha creado pero tenemos acceso, vm
lo que nos da acceso a la instancia del componente. Dentro de esta función, pasamos la respuesta de la solicitud API res
a nuestro método fetchData
que hemos creado para asignar el valor de esta respuesta post
para que podamos usarlo en nuestra plantilla. Ahora, si actualizamos nuestra /
ruta, notaremos que los datos se actualizan muy rápido y en ningún momento hay una página en blanco (siempre que la solicitud sea exitosa).
Transiciones
Vue viene con un transition/ transition
componente que permite una fácil implementación de transiciones y animaciones CSS . Esta función se puede ampliar para que funcione en la navegación entre rutas en Vue. He aquí un ejemplo:
template div div router-link to="/"Home/router-link /div transition name="slide-fade" router-view / /transition /div/templatestyle #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; } #nav { padding: 30px; } #nav a { font-weight: bold; color: #2c3e50; } #nav a.router-link-exact-active { color: #42b983; } .slide-fade-enter-active { transition: transform 0.3s cubic-bezier(1, 0.5, 0.8, 1), color 0.5s cubic-bezier(1, 0.5, 0.8, 1); } .slide-fade-leave-active { transition: transform 1s cubic-bezier(1, 0.5, 0.8, 1), color 1s cubic-bezier(1, 0.5, 0.8, 1); } .slide-fade-enter { color: mediumblue; transform: translateY(20px); } .slide-fade-leave-to { transform: translateX(100px); color: cyan; }/style
Aquí, agregamos una transición con el nombre slide-fade
a nuestra aplicación y la envolvemos alrededor de toda la navegación de ruta que tendría lugar en la aplicación. También estamos agregando un conjunto de estilos que controlan/definen la forma en que funcionarían las transiciones en nuestra aplicación. Sin estas reglas, no se produciría una transición visible. Ahora, si intentamos navegar desde la página de inicio a las publicaciones individuales, notaremos una transición deslizante y atenuada durante el proceso de navegación.
Hay dos tipos de transiciones basadas en rutas.
1. Transición por ruta
Este tipo de transición se define en el componente que representa una ruta y, por lo tanto, solo afecta la navegación hacia y desde dicha página. Esto nos da la posibilidad de definir una transición especial para rutas individuales si así lo deseamos. A continuación se muestra un ejemplo de cómo hacerlo.
template // add a transition component with name and mode props transition name="slide-fade" mode="in-out" div div h1{{ post.title }}/h1 p v-html="post.body"/p /div pEnd of page/p /div /transition/templatescript export default { name: "Post", props: ["id", "post"], };/scriptstyle //... .slide-fade-enter-active { transition: transform 2s cubic-bezier(1, 0.5, 0.8, 1), opacity 2s ease-in; } .slide-fade-leave-active { transition: transform 2s cubic-bezier(1, 0.5, 0.8, 1), opacity 2s ease-out; } .slide-fade-enter { opacity: 1; transform: skewY(20deg); } .slide-fade-leave-to { transform: skewY(-45deg); opacity: 0.5; }/style
Si intenta navegar fuera de esta página, notaremos que la página se distorsiona y se desvanece durante un período de tiempo 2s
a medida que cambia la navegación.
2. Transición dinámica basada en rutas
Esto es similar al método general de agregar transiciones a todas las rutas en su aplicación, pero tiene una diferencia importante, es decir, acepta un name
accesorio de transición dinámica que le brinda la posibilidad de cambiar el tipo de transición de la forma que desee. Creemos un ejemplo de cómo hacer esto.
Actualizaremos nuestro App.vue
archivo con un name
accesorio dinámico y lo configuraremos para elegir un nombre de transición según un valor.
template div div router-link to="/"Home/router-link /div transition :name="transitionName" router-view / /transition /div/templatescript export default { data() { return { transitionName: "slide-fade", }; }, watch: { $route(to, from, params) { const toParam = to.params to.params.id ? to.params.id : 0; this.transitionName = toParam % 2 === 0 ? "slide-left" : "slide-fade"; }, }, };/scriptstyle /* add transition styles */ .slide-fade-enter-active { transition: transform 0.3s cubic-bezier(1, 0.5, 0.8, 1), color 0.5s cubic-bezier(1, 0.5, 0.8, 1); } .slide-fade-leave-active { transition: transform 1s cubic-bezier(1, 0.5, 0.8, 1), color 1s cubic-bezier(1, 0.5, 0.8, 1); } .slide-fade-enter { color: mediumblue; transform: translateY(20px); } .slide-fade-leave-to { transform: translateX(100px); color: cyan; } .slide-left-enter-active { transition: transform 0.3s cubic-bezier(1, 0.5, 0.8, 1), color 0.5s cubic-bezier(1, 0.5, 0.8, 1); } .slide-left-leave-active { transition: transform 1s cubic-bezier(1, 0.5, 0.8, 1), color 1s cubic-bezier(1, 0.5, 0.8, 1); } .slide-left-enter { color: mediumblue; transform: translateY(20px); } .slide-left-leave-to { transform: skewY(90deg); color: cyan; }/style
Aquí, agregamos un nombre de transición dinámica que se define en la sección de secuencia de comandos de nuestra aplicación. También estamos vigilando $route
que cada vez que cambie, ejecutemos la función que verifica si la ruta actual tiene un parámetro de, id
de lo contrario, le damos un valor de 0
. También determinamos el nombre de la transición según el tipo de número id
(es decir, número par o impar). Ahora, si navegamos entre la página de destino y las diferentes publicaciones disponibles, observaremos que se producen dos tipos de transiciones mientras navegamos.
Metacampos
Los metacampos ayudan a proporcionar contexto adicional a una ruta determinada. Un ejemplo de dicho contexto sería si un usuario necesita estar autenticado para acceder a dicha ruta o no. Así es como se ve esto:
import Vue from 'vue'import VueRouter from 'vue-router'import Home from '../views/Home.vue'Vue.use(VueRouter)const routes = [{ path: '/', name: 'Home', component: Home, // add meta to this route meta: { requiresAuth: true } },]const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes})export default router
Aquí, agregamos una metapropiedad requiresAuth
a la /
ruta, lo que significa que queremos que los usuarios se autentiquen antes de que puedan acceder a esa ruta. Tenga en cuenta que 'requiresAuth' no es una propiedad estándar, por lo que puede elegir el nombre que prefiera. Cualquier valor que seleccione al final puede ser accesible en el $route
objeto. Este metacampo en este punto no impediría que usuarios no autorizados accedan a esa ruta; debemos conectarlo al protector de navegación.
Tal como su nombre lo indica, el protector de navegación ayuda a proteger y proteger las rutas según sus preferencias (es decir, redirigir a otra página o impedir la navegación). Esta característica funciona junto con los metacampos de ruta para proteger eficazmente las rutas de su aplicación. Hay 3 formas de agregar protección de enrutador en nuestra aplicación:
1. En componente
Vue ofrece la opción de configurar la protección de su enrutador para una ruta particular directamente dentro de sus componentes. Aquí hay un ejemplo en nuestro Home.vue
archivo:
template div p v-if="loading"Loading..../p ol v-else !-- add this text to your template -- p v-if="guest"Hi Guest/p li v-for="post in posts" :key="post.id" router-link :to="{ name: 'Post', params: { id: post.id, post: post } }" {{ post.title }} /router-link /li /ol /div/templatescript // @ is an alias to /src import axios from "axios"; export default { name: "Home", data() { return { posts: null, // add this property guest: false, loading: false, }; }, // add this function beforeRouteEnter(to, from, next) { if (to.matched.some((record) = record.meta.requiresAuth)) { // this route requires auth, check if logged in // if not, display guest greeting. const loggedIn = JSON.parse(localStorage.getItem("loggedIn")); if (!loggedIn) { next((vm) = { vm.guest = true; }); } else { next(); } } else { next(); // make sure to always call next()! } }, methods: {...} };/scriptstyle.../style
Aquí, agregamos un párrafo que solo es visible para usuarios no autenticados. También agregamos una propiedad que controla la visibilidad de este texto. Finalmente tenemos un método de enrutador beforeRouteEnter
en el que también conectamos el protector del enrutador y verificamos si el usuario está autenticado o no usando un valor que se agregaría manualmente más adelante. También tenemos una if/else
declaración, y dentro de esta declaración, cambiamos el valor de guest
dependiendo de la autenticación del usuario.
Y en su App.vue
, agregue este ciclo de vida al archivo.
export default { mounted() { localStorage.setItem("loggedIn", false); } };
Entonces, si actualiza su aplicación, deberíamos ver el texto que agregamos en el Home.vue
archivo.
2. Por ruta
También podemos agregar una protección de enrutador a nuestras aplicaciones por ruta en nuestro archivo de enrutador como otra propiedad dentro del objeto de ruta específico. He aquí un ejemplo:
{ path: '/', name: 'Home', component: Home, // add meta to this route meta: { requiresAuth: true }, beforeEnter: (to, from, next) = { if (to.name !== 'Home') { console.log('Per-Route navigation guard ti wa online'); next() } else next() } }
Aquí, agregamos una protección de enrutador a la /
ruta y actualmente solo estamos registrando un texto aleatorio en la consola, pero podemos hacer un par de cosas dentro de esta protección. Ahora, cada vez que visites la página de inicio, verás esto en tu consola:
3. Globalmente
También tenemos la opción de crear una protección de enrutador que funcione globalmente para cada parte de la aplicación (siempre que cumpla con la condición de protección). Esta protección global se crea en el archivo del enrutador al igual que la protección por ruta , pero en lugar de definirla dentro de un objeto de ruta específico, se define como un método de la router
instancia. Para ver un ejemplo de cómo funciona, crearemos un nuevo archivo y ruta en nuestra aplicación guest.vue
, le asignaremos un nombre y luego agregaremos las siguientes líneas de código al archivo.
template div h1Guest page/h1 pYou're seeing this page because you are not logged in/p /div/templatescript/scriptstyle/style
A continuación, creamos una /login
ruta con esta página recién creada y agregamos una metapropiedad a otras rutas existentes.
// create new route { path: '/login', name: 'login', component: () = import ( /* webpackChunkName: "auth" */ '../views/guest.vue') }, { path: '/:id', name: 'Post', props: true,a // add meta property meta: { requiresAuth: true }, component: () = import ( /* webpackChunkName: "post" */ '../views/Post.vue') }
Lo siguiente sería crear el protector de navegación global para todas las rutas que requieran autenticación y comprobar la autenticación del usuario mediante localStorage
(creado previamente). Redirigiríamos a los usuarios que tienen un loggedIn
valor falso a /login
.
router.beforeEach((to, from, next) = { if (to.matched.some((record) = record.meta.requiresAuth)) { // this route requires auth, check if logged in // if not, display guest greeting. const loggedIn = JSON.parse(localStorage.getItem("loggedIn")); if (!loggedIn) { next({ path: '/login' }); } else { next(); } } else { next(); // make sure to always call next()! }})
Entonces, si revisa su aplicación en su navegador, notará que actualmente se encuentra en esta página:
Si intentamos navegar a cualquiera de las rutas existentes, seremos redirigidos automáticamente a esta página sin importar lo que hagamos y eso significa que nuestro guardia de enrutador está protegiendo efectivamente esas rutas.
Conclusión
Podemos ver que Vue Router es una herramienta muy poderosa que se puede utilizar para algo más que crear rutas en su aplicación. Hemos aprendido cómo configurar el comportamiento de desplazamiento de las rutas en nuestra aplicación, las diferentes formas de agregar transiciones a las rutas en nuestra aplicación, cómo recuperar datos de una API antes de que se monte un componente, cómo usar la metapropiedad para nuestras rutas y la Diferentes formas de configurar la protección del enrutador.
Recursos
- Enrutador Vue
- Transiciones CSS en Vuejs y Nuxtjs
(ks, ra, yk, il)Explora más en
- API
- vista
- javascript
Deja un comentario