Получение данных в Nuxt

Хук fetch наиболее универсальный способ получения данных. Может использоваться в компонентах, макета, страницах, выполнятся на стороне сервера и клиента.

Получение данных в Nuxt

The fetch hook

Хук fetch наиболее универсальный способ получения данных. Может
использоваться в компонентах, макета, страницах, выполнятся на стороне
сервера и клиента. Может вызываться повторно для обновления данных.
Имеет доступ к this компонента.

Отлично подходит для заполнения HTML данными, которые затем
должны обновляться, например таблицы, постраничные данные и т.д.

fetch должен возвращать promise или использовать механику
async/await.

export default {
  data () {
    return {}
  },
  async fetch () {
    this.news = this.$api.get('news').readMany()
  }
} 

Полученные данные сохраняются в компоненте или во Vuex.store.

Размышления о fetch

Универсальность fetch() наводит на некоторые размышления и
вопросы о его работе.

Во-первых, на какой стадии жизненного цикла Nuxt выполняется запрос,
в каком окружении server или client? Это зависит от значений
параметра конфигурации ssr:

  • ssr: true, тогда fetch выполняется на стороне сервера, перед
    началом отрисовки, если используется target: server, или на этапе
    генерации статичного сайта при target: static
  • ssr: false, тогда fetch выполняется на клиенте при загрузке маршрута

Если по каким-то причинам при ssr: true требуется отключить исполнение
fetch на сервере, это можно сделать установив fetchOnServer: false в
параметрах компонента. Можно ограничить время исполнения параметром
fetchDelay.

Чтобы обновлять данные при изменении параметров запроса, например
фильтры или пагинация:

export default {
  watch: {
    '$route.query': '$fetch'
  }
}

fetch содержит несколько важных параметров

  • error - содержит ошибку, если запрос завершился неудачей
  • pending - отражает состояние выполнения true|false
  • timestamp - время последнего запроса, удобно для реализации кеширования
<template>
  <div v-if='$fetchState.pending'>Please wait...</div>
  <div v-else-if='$fetchState.error'>Oh no!</div>
  <div v-else>
    ...
  </div>
</template>

The asyncData hook

Загружает данные почти также как fetch, но со следующими различиями

  • Может использоваться только в компонентах страниц pages/**/*.vue
  • Объединяет полученные данные с данными компонента
  • Не имеет доступа к this компонента

asyncData выполняется при смене маршрута, и разрешается до отрисовки
страницы, поэтому и нет доступа к контексту компонента, его просто
еще не существует.

Взамен, в хук передается контекст Nuxt.

Чтобы обновить asyncData, выполнить его снова придется

  • обновить страницу целиком
  • выполнить this.$nuxt.refresh()

При этом this.$nuxt.refresh() обновит полностью все, включая asyncData
, fetch, перерисует страницу полностью. Поэтому, если надо только обновить
данные лучше использовать fetch.

asyncData отлично подходит для загрузки первичных данные страницы.
asyncData так же, как и fetch, не реагирует на изменения параметров
запроса, это нужно делать явно. Например,

export default {
    watchQuery: ['someQSParam'] //or true for all
}

Когда параметр someQSParam поменяется, fetch() и asyncData() будут
запущены заново.

Vuex Actions

Еще один подход, использование действий Vuex. Можно использовать dispatch
для вызова асинхронных функций и получения данных. Это делает процесс
получения данных сложнее, но позволяет повторно использовать методы в
разных компонентах и хуках. Контроль за доступностью данных становиться
сложнее. Отрисовка и логика шаблонов требует проверки доступности данных,
или использования computed методов, для дополнительной проверки.

Router middleware

Если получение данных критично, данные должны быть доступны до отрисовки
компонента можно использовать middleware. Функции выполняются до
отрисовки и создания компонентов, данные не могут сохраняться напрямую
в компонентах, но могут быть сохранены во Vuex.store.

Использование middleware может потребоваться когда данные необходимы
на каждой странице проекта. Объявить middleware можно тремя способами:

  • в конфигурации Nuxt (для определенного маршрута)
  • в макетах (layout) (для страниц и определенного макета)
  • в странице (page) (только для определенной страницы)