No desenvolvimento de aplicações Vue.js, o Vue Router e o Vuex são ferramentas fundamentais. O Vue Router é responsável pela navegação em Aplicações de Página Única (SPA), enquanto o Vuex gerencia o estado global da aplicação de forma centralizada. A integração entre essas duas bibliotecas, particularmente a sincronização do estado da rota com o Vuex, oferece uma abordagem poderosa para gerenciar e compartilhar informações de navegação, otimizando o processo de desenvolvimento.
Integrando Vue Router e Vuex
Por Que Realizar a Integração?
O gerenciamento do estado da rota é uma preocupação importante em SPAs. Frequentemente, é necessário acessar detalhes da rota em diferentes componentes – por exemplo, para destacar links de navegação, carregar dados específicos com base em parâmetros de URL ou controlar aspectos do layout. Ao sincronizar o estado da rota com o Vuex, essas informações tornam-se globalmente acessíveis e consistentes, eliminadno a necessidade de passar dados entre componentes manualmente e garantindo uma única fonte de verdade para o estado da rota.
Etapas para a Configuração
1. Instalação das Bibliotecas
Primeiramente, certifique-se de que Vue Router e Vuex estão incluídos nas dependências do seu projeto. Caso não estejam, utilize o seguinte comando:
npm install vue-router vuex
Este comando adicionará as bibliotecas ao seu projeto, preparando-o para a integração.
2. Inicialização do Vuex Store e Vue Router
Crie e configure as instâncias para o gerenciador de estado (Vuex) e o roteador (Vue Router).
store/index.js (Configuração do Vuex Store)
import { createStore } from 'vuex'; // Para Vuex 4+
// Para Vuex 3-:
// import Vue from 'vue';
// import Vuex from 'vuex';
// Vue.use(Vuex);
const gerenciadorEstado = createStore({ // Para Vuex 3-, use new Vuex.Store
state: {
infoRotaAtual: null
},
mutations: {
atualizarInfoRota(state, rota) {
state.infoRotaAtual = rota;
}
}
});
export default gerenciadorEstado;
Neste arquivo, definimos um armazenamento Vuex. O state contém infoRotaAtual, que armazenará o objeto da rota ativa. A mutação atualizarInfoRota é o método exclusivo para modificar este estado, garantindo que todas as mudanças sejam rastreáveis.
router/index.js (Configuração do Vue Router)
import { createRouter, createWebHistory } from 'vue-router'; // Para Vue Router 4+
// Para Vue Router 3-:
// import Vue from 'vue';
// import VueRouter from 'vue-router';
// Vue.use(VueRouter);
const definicoesRotas = [
// Suas definições de rota serão adicionadas aqui
];
const roteador = createRouter({ // Para Vue Router 3-, use new VueRouter
history: createWebHistory(), // Necessário para Vue Router 4+
routes: definicoesRotas
});
export default roteador;
Aqui, o Vue Router é configurado com um array de definicoesRotas, que será preenchido com os mapeamentos entre URLs e componentes da sua aplicação.
3. Conectando Vue Router e Vuex no main.js
Importe e utilize as instâncias do gerenciadorEstado e roteador no arquivo principal da sua aplicação Vue.
import { createApp } from 'vue'; // Para Vue 3+
import App from './App.vue';
import roteador from './router';
import gerenciadorEstado from './store';
const app = createApp(App); // Para Vue 2, use new Vue({ ... })
app.use(roteador);
app.use(gerenciadorEstado);
app.mount('#app');
/*
// Exemplo para Vue 2:
import Vue from 'vue';
import App from './App.vue';
import roteador from './router';
import gerenciadorEstado from './store';
new Vue({
el: '#app',
router: roteador,
store: gerenciadorEstado,
render: h => h(App)
});
*/
Nesta etapa, o Vue Router e o Vuex são conectados à instância principal do Vue, tornando suas funcionalidades disponíveis em toda a aplicação.
Sincronizando o Estado da Rota com o Vuex
Monitorando Alterações de Rota
Para manter o Vuex atualizado com a rota atual, é preciso monitorar as transições de rota. O Vue Router oferece os guarda de navegação, como o beforeEach, que é executado antes de cada navegação.
// router/index.js (Com lógica de sincronização)
import { createRouter, createWebHistory } from 'vue-router';
import gerenciadorEstado from '../store'; // Importa o store
const definicoesRotas = [
// ... suas rotas ...
];
const roteador = createRouter({
history: createWebHistory(),
routes: definicoesRotas
});
roteador.beforeEach((rotaDestino, rotaOrigem, proximo) => {
gerenciadorEstado.commit('atualizarInfoRota', rotaDestino);
proximo(); // Continua a navegação
});
export default roteador;
Dentro do beforeEach, invocamos gerenciadorEstado.commit('atualizarInfoRota', rotaDestino), que aciona a mutação em nosso Vuex store, persistindo o objeto da próxima rota. O chamado a proximo() é crucial para permitir que a navegação continue seu curso.
Acessando o Estado de Rota Sincronizado nos Componentes
Com o estado da rota no Vuex, qualquer componente pode acessar essas informações de maneira simples.
<template>
<div>
<p>Nome da Rota Ativa: {{ infoRotaAtual ? infoRotaAtual.name : 'Indisponível' }}</p>
</div>
</template>
<script>
import { mapState } from 'vuex';
export default {
computed: {
...mapState({
infoRotaAtual: state => state.infoRotaAtual
})
}
};
</script>
Aqui, mapState é utilizado para mapear a propriedade infoRotaAtual do Vuex para uma propriedade computada no componente. Isso permite que a informação seja exibida e utilizada no template de forma reativa.
Exemplo Completo com Vue 3
Abaixo, um exemplo completo que demonstra a configuração e a sincronização em uma aplicação Vue 3:
store/index.js
import { createStore } from 'vuex';
const gerenciadorEstado = createStore({
state: {
infoRotaAtual: null
},
mutations: {
atualizarInfoRota(state, rota) {
state.infoRotaAtual = rota;
}
}
});
export default gerenciadorEstado;
router/index.js
import { createRouter, createWebHistory } from 'vue-router';
import gerenciadorEstado from '../store'; // Importa o store
import VistaInicial from '../views/VistaInicial.vue';
import VistaSobre from '../views/VistaSobre.vue';
const definicoesRotas = [
{
path: '/',
name: 'Dashboard',
component: VistaInicial
},
{
path: '/sobre',
name: 'Informacoes',
component: VistaSobre
}
];
const roteador = createRouter({
history: createWebHistory(),
routes: definicoesRotas
});
roteador.beforeEach((rotaDestino, rotaOrigem, proximo) => {
gerenciadorEstado.commit('atualizarInfoRota', rotaDestino);
proximo();
});
export default roteador;
views/VistaInicial.vue
<template>
<div>
<h1>Bem-vindo à Vista Inicial</h1>
<p>Este é o conteúdo da página principal.</p>
</div>
</template>
<script>
export default {
name: 'VistaInicial'
};
</script>
views/VistaSobre.vue
<template>
<div>
<h1>Sobre a Aplicação</h1>
<p>Detalhes e informações sobre o projeto.</p>
</div>
</template>
<script>
export default {
name: 'VistaSobre'
};
</script>
App.vue
<template>
<div id="app">
<nav>
<router-link to="/">Início</router-link> |
<router-link to="/sobre">Sobre</router-link>
</nav>
<router-view></router-view>
<p>Estado da Rota (Vuex): <strong>{{ infoRotaAtual ? infoRotaAtual.name : 'Nenhuma rota ativa' }}</strong></p>
</div>
</template>
<script>
import { mapState } from 'vuex';
export default {
name: 'ComponenteRaiz',
computed: {
...mapState({
infoRotaAtual: state => state.infoRotaAtual
})
}
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
nav {
margin-bottom: 20px;
}
nav a {
font-weight: bold;
color: #2c3e50;
padding: 0 10px;
text-decoration: none;
}
nav a.router-link-exact-active {
color: #42b983;
}
</style>