如何正确使用 Nuxt 2.12 中新的 fetch() 钩子进行 SSR?
How to properly use the new fetch() hook in Nuxt 2.12 for SSR?
我将 Nuxt 更新到最新版本,因为他们引入了新的 fetch()
钩子。
在我的项目中,我正在从 Prismic 检索数据。之前,我使用的是 asyncData()
,但是在导航时,需要一些时间才能呈现调用 asyncData()
的页面(这是它的工作原理)。
理想的解决方案是在该特定页面上导航,并在检索数据时显示加载动画。
新的 fetch()
挂钩似乎很合适,因为它公开了 $fetchState.pending
以检查操作的状态。
现在,代码(我正在从商店的类别中检索子类别):
data(){
return{
docs: []
}
},
async fetch() {
try{
const res = await this.$prismic.api.query(this.$prismic.predicates.at('my.category.uid', this.$route.params.sub))
const el = res.results[0]
const query = await this.$prismic.api.query([this.$prismic.predicates.at('document.type','sub-category'), this.$prismic.predicates.at('my.sub-category.category', el.id)], { orderings: '[my.sub-category.position, my.sub-category.title]' })
this.docs = query.results
}
catch (e) {
console.log(e)
}
}
这至少在客户端有效。这对正确的 SSR 有用吗?我的意思是,在 asyncData()
(调用服务器端)中,this
不可访问,data()
也不可访问。如果这是正确的解决方案,那么使用 asyncData()
而不是 fetch()
有什么意义呢?
如果您正在寻找一种方法来为您的页面组件设置加载状态,您可以将数据与 asyncData 一起使用,
data(){
return{
loading: true
}
},
async asyncData(context) {
try{
const res = await context.app.$prismic.api.query(context.app.$prismic.predicates.at('my.category.uid', context.app.$route.params.sub))
const el = res.results[0]
const query = await context.app.$prismic.api.query([context.app.$prismic.predicates.at('document.type','sub-category'), context.app.$prismic.predicates.at('my.sub-category.category', el.id)], { orderings: '[my.sub-category.position, my.sub-category.title]' })
const docs = query.results
const loading = false
return {docs, el, loading}
}
catch (e) {
console.log(e)
}
}
如果您使用 prismic,(如果您没有将其注册为插件)您可以通过插件将 prismic 注入到上下文中
import prismic from 'prismic-javascript'
export default (inject) => {
inject('prismic', prismic)
}
现在您可以在上下文中访问 $prismic。
我在处理加载状态时使用的另一种方法是使用存储模块来处理请求的状态。
plugins/loading.js
export default ({store},inject) => {
inject('changeLoading', function(){
store.dispatch('changeLoading')
}
)
}
store/index.js
export const state = () => ({
loading: false
});
export const mutations = {
CHANGE_LOADING(state){
state.loading = !state.loading
}
}
export const actions = {
changeLoading({commit}){
commit('CHANGE_LOADING')
}
}
export const getters = {
getLoading(state){
return state.loading
}
}
所以现在您的组件中没有本地加载状态,您可以在您的商店中有一个可以更改和获取的集中状态。
data(){
return{
loading: this.$store.getters['getLoading']
}
},
async asyncData(context) {
try{
context.app.$changeLoading()
const prismicData = await context.app.$prismic(...)
context.app.$changeLoading()
return {prismicData}
}
catch (e) {
context.app.$changeLoading()
console.log(e)
}
}
就SSR而言,fetch
的使用方式与asyncData
的使用方式相同(虽然页面转换时间有所不同)。
fetch
和asyncData
的区别:
asyncData
无法访问 this
,而 fetch
(在 Nuxt >= 2.12 中)可以。
asyncData
的return值设置组件的数据,而fetch
的return值不设置,因为fetch
已经有访问权限this
,所以它可以直接设置 data
道具。
fetch
由两个options(fetchOnServer
和fetchDelay
)控制,而asyncData
没有选项。当fetchOnServer
(默认true
)设置为false
时,fetch
钩子只在客户端调用。
fetch
与$fetchState
对象耦合,提供pending
和timestamp
(与fetch操作的当前状态有关);和 error
函数(允许您显示错误消息)。请注意,asyncData
在其 context
参数中还提供了 error
函数。
fetch
允许更快的页面转换(根据 RFC 27)。
asyncData
仅对页面可用,而fetch
可被任何组件(包括页面)使用。
除了上述差异外,这两种方法的语义是相同的。
似乎 fetch
是 asyncData
的非正式继任者,尽管两者同时存在而没有弃用通知。由于 fetch
提供了更多功能并解决了 asyncData
的问题,我建议只使用 fetch
。
已解决:Nuxt 提示我一个小警告说 "node-fetch" 至少在版本 2.6.0 是必需的。出于某种原因,我的是 2.1.2.
我将 Nuxt 更新到最新版本,因为他们引入了新的 fetch()
钩子。
在我的项目中,我正在从 Prismic 检索数据。之前,我使用的是 asyncData()
,但是在导航时,需要一些时间才能呈现调用 asyncData()
的页面(这是它的工作原理)。
理想的解决方案是在该特定页面上导航,并在检索数据时显示加载动画。
新的 fetch()
挂钩似乎很合适,因为它公开了 $fetchState.pending
以检查操作的状态。
现在,代码(我正在从商店的类别中检索子类别):
data(){
return{
docs: []
}
},
async fetch() {
try{
const res = await this.$prismic.api.query(this.$prismic.predicates.at('my.category.uid', this.$route.params.sub))
const el = res.results[0]
const query = await this.$prismic.api.query([this.$prismic.predicates.at('document.type','sub-category'), this.$prismic.predicates.at('my.sub-category.category', el.id)], { orderings: '[my.sub-category.position, my.sub-category.title]' })
this.docs = query.results
}
catch (e) {
console.log(e)
}
}
这至少在客户端有效。这对正确的 SSR 有用吗?我的意思是,在 asyncData()
(调用服务器端)中,this
不可访问,data()
也不可访问。如果这是正确的解决方案,那么使用 asyncData()
而不是 fetch()
有什么意义呢?
如果您正在寻找一种方法来为您的页面组件设置加载状态,您可以将数据与 asyncData 一起使用,
data(){
return{
loading: true
}
},
async asyncData(context) {
try{
const res = await context.app.$prismic.api.query(context.app.$prismic.predicates.at('my.category.uid', context.app.$route.params.sub))
const el = res.results[0]
const query = await context.app.$prismic.api.query([context.app.$prismic.predicates.at('document.type','sub-category'), context.app.$prismic.predicates.at('my.sub-category.category', el.id)], { orderings: '[my.sub-category.position, my.sub-category.title]' })
const docs = query.results
const loading = false
return {docs, el, loading}
}
catch (e) {
console.log(e)
}
}
如果您使用 prismic,(如果您没有将其注册为插件)您可以通过插件将 prismic 注入到上下文中
import prismic from 'prismic-javascript'
export default (inject) => {
inject('prismic', prismic)
}
现在您可以在上下文中访问 $prismic。
我在处理加载状态时使用的另一种方法是使用存储模块来处理请求的状态。
plugins/loading.js
export default ({store},inject) => {
inject('changeLoading', function(){
store.dispatch('changeLoading')
}
)
}
store/index.js
export const state = () => ({
loading: false
});
export const mutations = {
CHANGE_LOADING(state){
state.loading = !state.loading
}
}
export const actions = {
changeLoading({commit}){
commit('CHANGE_LOADING')
}
}
export const getters = {
getLoading(state){
return state.loading
}
}
所以现在您的组件中没有本地加载状态,您可以在您的商店中有一个可以更改和获取的集中状态。
data(){
return{
loading: this.$store.getters['getLoading']
}
},
async asyncData(context) {
try{
context.app.$changeLoading()
const prismicData = await context.app.$prismic(...)
context.app.$changeLoading()
return {prismicData}
}
catch (e) {
context.app.$changeLoading()
console.log(e)
}
}
就SSR而言,fetch
的使用方式与asyncData
的使用方式相同(虽然页面转换时间有所不同)。
fetch
和asyncData
的区别:
asyncData
无法访问this
,而fetch
(在 Nuxt >= 2.12 中)可以。asyncData
的return值设置组件的数据,而fetch
的return值不设置,因为fetch
已经有访问权限this
,所以它可以直接设置data
道具。fetch
由两个options(fetchOnServer
和fetchDelay
)控制,而asyncData
没有选项。当fetchOnServer
(默认true
)设置为false
时,fetch
钩子只在客户端调用。fetch
与$fetchState
对象耦合,提供pending
和timestamp
(与fetch操作的当前状态有关);和error
函数(允许您显示错误消息)。请注意,asyncData
在其context
参数中还提供了error
函数。fetch
允许更快的页面转换(根据 RFC 27)。asyncData
仅对页面可用,而fetch
可被任何组件(包括页面)使用。
除了上述差异外,这两种方法的语义是相同的。
似乎 fetch
是 asyncData
的非正式继任者,尽管两者同时存在而没有弃用通知。由于 fetch
提供了更多功能并解决了 asyncData
的问题,我建议只使用 fetch
。
已解决:Nuxt 提示我一个小警告说 "node-fetch" 至少在版本 2.6.0 是必需的。出于某种原因,我的是 2.1.2.