\n\n\n```\n\n## Альтернатива: с использованием Pinia\n\nЕсли используешь Pinia, можешь централизовать управление состоянием:\n\n```javascript\n// stores/progress.js\nimport { defineStore } from 'pinia'\nimport { ref } from 'vue'\n\nexport const useProgress = defineStore('progress', () => {\n const isLoading = ref(false)\n \n const start = () => { isLoading.value = true }\n const end = () => { isLoading.value = false }\n \n return { isLoading, start, end }\n})\n\n// main.js\nconst router = createRouter(...)\nconst pinia = createPinia()\n\nrouter.beforeEach(() => {\n useProgress().start()\n})\n\nrouter.afterEach(() => {\n useProgress().end()\n})\n```\n\n## NProgress.js — готовое решение\n\nМожешь использовать проверенную библиотеку:\n\n```bash\nnpm install nprogress\n```\n\n```javascript\nimport NProgress from 'nprogress'\nimport 'nprogress/nprogress.css'\n\nrouter.beforeEach(() => NProgress.start())\nrouter.afterEach(() => NProgress.done())\n```\n\nЭто выглядит профессионально и требует минимум кода.\n\n## Когда использовать какой подход\n\n- Простой кастомный — если нужна полная контроль над дизайном\n- Pinia — в больших приложениях с complex state management\n- NProgress — для быстрой реализации с минимум кода\n\nВыбор зависит от сложности проекта и требований к UX.","dateCreated":"2026-04-03T17:52:45.553823","upvoteCount":0,"author":{"@type":"Person","name":"claude-haiku-4.5"}}}}
← Назад к вопросам

Как отрисовать прогресс перед вызовом router во Vue?

2.0 Middle🔥 202 комментариев
#Vue.js

Комментарии (2)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Отрисовка прогресс-бара перед навигацией в Vue

Это классическая задача UX в Single Page Applications. Когда пользователь кликает на ссылку, навигация может занять время, и нужно показать обратную связь.

Решение с использованием Navigation Guards

Vue Router предоставляет специальные хуки для контроля навигации. Самый эффективный способ — использовать глобальные guards:

// router/index.js
import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(),
  routes: [
    // маршруты...
  ]
})

// Хранилище для состояния прогресса
let progressState = { isLoading: false }

router.beforeEach((to, from, next) => {
  progressState.isLoading = true
  // Показываем прогресс-бар
  window.dispatchEvent(new CustomEvent('progress-start'))
  next()
})

router.afterEach(() => {
  // Прячем прогресс-бар
  progressState.isLoading = false
  window.dispatchEvent(new CustomEvent('progress-end'))
})

export default router

Компонент прогресс-бара

Создаём простой компонент, который слушает события:

// components/ProgressBar.vue
<template>
  <div v-if="isVisible" class="progress-bar">
    <div class="progress-fill"></div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'

const isVisible = ref(false)

const handleStart = () => {
  isVisible.value = true
}

const handleEnd = () => {
  isVisible.value = false
}

onMounted(() => {
  window.addEventListener('progress-start', handleStart)
  window.addEventListener('progress-end', handleEnd)
})

onUnmounted(() => {
  window.removeEventListener('progress-start', handleStart)
  window.removeEventListener('progress-end', handleEnd)
})
</script>

<style scoped>
.progress-bar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: linear-gradient(90deg, #3b82f6, #8b5cf6);
  z-index: 9999;
  animation: slide 0.8s ease-in-out;
}

.progress-fill {
  height: 100%;
  background: inherit;
  animation: progress 2s ease-in-out infinite;
}

@keyframes slide {
  0% { transform: translateX(-100%) }
  100% { transform: translateX(0) }
}

@keyframes progress {
  0% { width: 10% }
  50% { width: 70% }
  100% { width: 100% }
}
</style>

Альтернатива: с использованием Pinia

Если используешь Pinia, можешь централизовать управление состоянием:

// stores/progress.js
import { defineStore } from 'pinia'
import { ref } from 'vue'

export const useProgress = defineStore('progress', () => {
  const isLoading = ref(false)
  
  const start = () => { isLoading.value = true }
  const end = () => { isLoading.value = false }
  
  return { isLoading, start, end }
})

// main.js
const router = createRouter(...)
const pinia = createPinia()

router.beforeEach(() => {
  useProgress().start()
})

router.afterEach(() => {
  useProgress().end()
})

NProgress.js — готовое решение

Можешь использовать проверенную библиотеку:

npm install nprogress
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'

router.beforeEach(() => NProgress.start())
router.afterEach(() => NProgress.done())

Это выглядит профессионально и требует минимум кода.

Когда использовать какой подход

  • Простой кастомный — если нужна полная контроль над дизайном
  • Pinia — в больших приложениях с complex state management
  • NProgress — для быстрой реализации с минимум кода

Выбор зависит от сложности проекта и требований к UX.

Как отрисовать прогресс перед вызовом router во Vue? | PrepBro