问题
今天写代码的时候发现nuxt的钩子不在服务端执行,而是在客户端执行,并且mounted钩子不会在fetch钩子执行结束后再执行,导致一些数据获取顺序不对渲染结果出错
main.vue
<template>
<div>
<el-container>
<Main v-if="can"></Main>
</el-container>
</div>
</template>
<script>
import Main from '@/components/layout/layoutMain'
export default {
components: {
Main,
},
data() {
return {
can: false
}
},
mounted() {
setTimeout(() => {
this.can = true
}, 3000)}
</script>
问题:Main组件中的fetch在客户端执行
问题原因
Nuxt.js 启用服务端渲染 (SSR) 时,服务端渲染会针对初始加载时需要显示的所有组件执行,初始不显示的组件不会执行SSR。
也就是说:
- 只有那些在初始页面加载时实际渲染到页面上的组件才会在服务端执行其钩子函数。那些通过懒加载(如 v-if、v-show 或动态组件)或在用户交互后才会显示的组件,不会在服务端渲染阶段执行其钩子函数。
- 这些懒加载或动态组件的钩子函数会在客户端激活阶段或在组件实际渲染到页面时执行。
案例:
pages/index.vue
<template>
<div>
<h1>Home Page</h1>
<AsyncComponent v-if="showAsyncComponent" />
</div>
</template>
<script>
import AsyncComponent from '~/components/AsyncComponent.vue';
export default {
components: {
AsyncComponent
},
data() {
return {
showAsyncComponent: false
};
},
async asyncData({ params }) {
console.log('Page asyncData');
// 异步获取数据
return { pageData: await fetchData(params.id) };
},
fetch() {
console.log('Page fetch');
this.pageData = fetchData(params.id);
},
mounted() {
// 模拟用户交互显示异步组件
console.log('Page mounted')
setTimeout(() => {
this.showAsyncComponent = true;
}, 2000);
}
};
</script>
components/AsyncComponent.vue
<template>
<div>
<h2>Async Component</h2>
</div>
</template>
<script>
export default {
async asyncData({ params }) {
console.log('AsyncComponent asyncData');
// 异步获取数据
return { componentData: await fetchData(params.id) };
},
fetch() {
console.log('AsyncComponent fetch');
this.componentData = fetchData(params.id);
}
mounted() {
console.log('AsyncComponent mounted')
}
};
</script>
该页面,服务端渲染阶段执行结果:
Page asyncData
Page fetch
客户端渲染阶段执行结果:
Page mounted
AsyncComponent asyncData
AsyncComponent fetch
AsyncComponent mounted
并且此时子组件的mounted在fetch后面执行,但是不是等fetch执行完之后才执行
fetch在客户端执行时和mounted的执行顺序
fetch在客户端执行时,mounted 不一定会在fetch 执行完再执行,具体执行顺序:
- 组件实例化。
- fetch 钩子开始执行(如果有异步任务,会继续进行)。
- mounted 钩子执行(不会等待 fetch 钩子完成)。
943

被折叠的 条评论
为什么被折叠?



