Получение данных в Nuxt
Хук fetch наиболее универсальный способ получения данных. Может использоваться в компонентах, макета, страницах, выполнятся на стороне сервера и клиента.
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) (только для определенной страницы)