Сохранение параметров маршрута в state

В приложениях на Vue с использованием Vue Router часто возникает необходимость не просто переходить между страницами, но и сохранять состояние маршрута для дальнейшего использования. Это особенно актуально для динамических маршрутов, фильтров, пагинации и форм с множественными шагами. Vue Router предоставляет доступ к параметрам маршрута через объект route, но для долговременного хранения и управления состоянием удобнее использовать хранилище, например Vuex или Composition API с reactive/ref.

Получение параметров маршрута

Каждый компонент, который рендерится через <router-view>, получает объект маршрута через this.$route (Options API) или useRoute() (Composition API). В объекте маршрута доступны:

  • params — динамические сегменты маршрута, определенные через :param в пути.
  • query — параметры запроса, передаваемые через URL после ?.
  • name — имя маршрута, если он был задан при определении.

Пример доступа к параметрам:

// Options API
export default {
  mounted() {
    console.log(this.$route.params.id);
    console.log(this.$route.query.filter);
  }
}

// Composition API
import { useRoute } from 'vue-router';
import { onMounted } from 'vue';

export default {
  setup() {
    const route = useRoute();

    onMounted(() => {
      console.log(route.params.id);
      console.log(route.query.filter);
    });
  }
}

Сохранение параметров в state

Чтобы параметры маршрута сохранялись при навигации и могли использоваться другими компонентами, их можно сохранять в глобальном хранилище Vuex или в локальном состоянии компонента. Преимущества хранения в state:

  • Состояние сохраняется даже при переходе на другие маршруты.
  • Упрощается управление параметрами для фильтров, пагинации и динамического контента.
  • Легко реализуется реактивная логика на изменения параметров.

Пример с Vuex:

// store.js
import { createStore } from 'vuex';

export const store = createStore({
  state: {
    routeParams: {},
    queryParams: {}
  },
  mutations: {
    setRouteParams(state, params) {
      state.routeParams = params;
    },
    setQueryParams(state, query) {
      state.queryParams = query;
    }
  }
});
// Component.vue
import { useStore } from 'vuex';
import { useRoute, onBeforeRouteUpdate } from 'vue-router';

export default {
  setup() {
    const store = useStore();
    const route = useRoute();

    store.commit('setRouteParams', route.params);
    store.commit('setQueryParams', route.query);

    onBeforeRouteUpdate((to) => {
      store.commit('setRouteParams', to.params);
      store.commit('setQueryParams', to.query);
    });
  }
}

Реактивное отслеживание изменений параметров маршрута

Vue Router позволяет подписываться на изменения маршрута без перезагрузки компонента, используя watch на объект route или хук onBeforeRouteUpdate. Это особенно полезно для фильтров и пагинации:

import { watch } from 'vue';
import { useRoute } from 'vue-router';
import { reactive } from 'vue';

export default {
  setup() {
    const route = useRoute();
    const state = reactive({
      id: route.params.id,
      filter: route.query.filter
    });

    watch(route, (newRoute) => {
      state.id = newRoute.params.id;
      state.filter = newRoute.query.filter;
    });
  }
}

Синхронизация с локальным состоянием компонента

Иногда требуется хранить параметры маршрута локально, чтобы компонент мог изменять их без немедленного обновления URL. В этом случае можно инициализировать состояние из route при монтировании и затем отслеживать изменения:

import { reactive, onMounted, watch } from 'vue';
import { useRoute } from 'vue-router';

export default {
  setup() {
    const route = useRoute();
    const localState = reactive({
      id: null,
      filter: ''
    });

    onMounted(() => {
      localState.id = route.params.id;
      localState.filter = route.query.filter;
    });

    watch(route, (newRoute) => {
      localState.id = newRoute.params.id;
      localState.filter = newRoute.query.filter;
    });
  }
}

Передача сохранённого состояния при навигации

Для восстановления состояния после перехода на другой маршрут полезно использовать методы router.push() или router.replace(), передавая сохранённые параметры:

import { useRouter } from 'vue-router';

export default {
  setup() {
    const router = useRouter();

    function goToNextPage(savedParams) {
      router.push({
        name: 'nextPage',
        params: savedParams.routeParams,
        query: savedParams.queryParams
      });
    }

    return { goToNextPage };
  }
}

Практические рекомендации

  • Для небольших приложений достаточно локального состояния в компоненте.
  • Для сложных приложений с множеством компонентов и маршрутов рекомендуется использовать Vuex или Pinia для централизованного хранения параметров маршрута.
  • Всегда синхронизируйте изменения параметров маршрута через watch или хуки, чтобы состояние оставалось актуальным.
  • Если необходимо восстановление состояния после перезагрузки страницы, следует сохранять параметры маршрута в localStorage или sessionStorage и инициировать state при старте приложения.

С помощью такой стратегии параметры маршрута становятся полноценной частью состояния приложения, позволяя создавать гибкую навигацию и управлять пользовательским интерфейсом без потери данных.