Работа с REST API в Vue.js: полное руководство

REST API в Vue.js Vue.js

В современной веб-разработке взаимодействие с REST API является ключевым аспектом большинства приложений. В этом уроке мы детально рассмотрим работу с HTTP-запросами в Vue.js используя библиотеку Axios

Установка и настройка Axios

npm install axios
# или
yarn add axios

Базовая настройка в проекте:

// src/plugins/axios.js
import axios from 'axios'

const axiosInstance = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 5000,
  headers: {
    'Content-Type': 'application/json'
  }
})

export default axiosInstance

Использование в компоненте:

// src/components/UserList.vue
import axios from '@/plugins/axios'

export default {
  data() {
    return {
      users: [],
      loading: false,
      error: null
    }
  },
  methods: {
    async fetchUsers() {
      this.loading = true
      try {
        const response = await axios.get('/users')
        this.users = response.data
      } catch (error) {
        this.error = error.message
      } finally {
        this.loading = false
      }
    }
  }
}

Обработка ошибок

Глобальная обработка ошибок:

// src/plugins/axios.js
axiosInstance.interceptors.response.use(
  response => response,
  error => {
    if (error.response) {
      switch (error.response.status) {
        case 401:
          // Перенаправление на страницу логина
          router.push('/login')
          break
        case 404:
          // Обработка "не найдено"
          break
        case 500:
          // Обработка серверных ошибок
          break
      }
    }
    return Promise.reject(error)
  }
)

Локальная обработка ошибок:

async createUser(userData) {
  try {
    const response = await axios.post('/users', userData)
    this.$notify({
      type: 'success',
      message: 'Пользователь успешно создан'
    })
    return response.data
  } catch (error) {
    this.$notify({
      type: 'error',
      message: error.response?.data?.message || 'Произошла ошибка'
    })
    throw error
  }
}

Interceptors (Перехватчики)

// Перехватчик запросов
axios.interceptors.request.use(
  config => {
    // Добавление токена авторизации
    const token = localStorage.getItem('token')
    if (token) {
      config.headers.Authorization = `Bearer ${token}`
    }
    return config
  },
  error => Promise.reject(error)
)

// Перехватчик ответов
axios.interceptors.response.use(
  response => {
    // Обработка успешного ответа
    return response
  },
  error => {
    // Обработка ошибок
    return Promise.reject(error)
  }
)

Кэширование запросов

// src/utils/cacheService.js
const cache = new Map()

export const cacheService = {
  set(key, data, ttl = 60000) {
    cache.set(key, {
      data,
      timestamp: Date.now(),
      ttl
    })
  },

  get(key) {
    const cached = cache.get(key)
    if (!cached) return null

    if (Date.now() - cached.timestamp > cached.ttl) {
      cache.delete(key)
      return null
    }

    return cached.data
  }
}

// Использование кэширования
async function fetchDataWithCache(url) {
  const cachedData = cacheService.get(url)
  if (cachedData) return cachedData

  const response = await axios.get(url)
  cacheService.set(url, response.data)
  return response.data
}

Отмена запросов

export default {
  data() {
    return {
      abortController: null
    }
  },
  methods: {
    async fetchData() {
      // Отмена предыдущего запроса
      if (this.abortController) {
        this.abortController.abort()
      }

      // Создание нового контроллера
      this.abortController = new AbortController()

      try {
        const response = await axios.get('/api/data', {
          signal: this.abortController.signal
        })
        return response.data
      } catch (error) {
        if (axios.isCancel(error)) {
          console.log('Запрос отменен')
        } else {
          console.error('Ошибка:', error)
        }
      }
    }
  },
  beforeUnmount() {
    if (this.abortController) {
      this.abortController.abort()
    }
  }
}

Загрузка файлов

async uploadFile(file) {
  const formData = new FormData()
  formData.append('file', file)

  try {
    const response = await axios.post('/upload', formData, {
      headers: {
        'Content-Type': 'multipart/form-data'
      },
      onUploadProgress: progressEvent => {
        const percentCompleted = Math.round(
          (progressEvent.loaded * 100) / progressEvent.total
        )
        this.uploadProgress = percentCompleted
      }
    })
    return response.data
  } catch (error) {
    console.error('Ошибка загрузки:', error)
    throw error
  }
}

Пример компонента загрузки файлов:

<template>
  <div class="upload-component">
    <input type="file" @change="handleFileSelect">
    <div v-if="uploading" class="progress">
      Загрузка: {{ progress }}%
      <div class="progress-bar" :style="{ width: `${progress}%` }"></div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      uploading: false,
      progress: 0
    }
  },
  methods: {
    async handleFileSelect(event) {
      const file = event.target.files[0]
      if (!file) return

      this.uploading = true
      this.progress = 0

      try {
        await this.uploadFile(file)
        this.$emit('upload-success')
      } catch (error) {
        this.$emit('upload-error', error)
      } finally {
        this.uploading = false
      }
    }
  }
}
</script>

Практические советы

  1. Всегда используйте try/catch для обработки ошибок
  2. Реализуйте механизм повторных попыток для важных запросов
  3. Используйте кэширование для оптимизации производительности
  4. Не забывайте об отмене запросов при размонтировании компонентов
  5. Реализуйте индикаторы загрузки для улучшения UX

Это базовое руководство по работе с REST API в Vue.js. Каждый раздел можно расширить дополнительными примерами и случаями использования в зависимости от потребностей проекта

Еще больше уроков для изучения Vue

Оцените статью
Уроки программирования
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest
0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x