Sincronização do Estado de Rota do Vue Router com Vuex

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>

Tags: Vue.js Vue Router Vuex Gerenciamento de Estado roteamento

Publicado em 7-22 07:19