Nuxt中获取大API响应时如何避免阻塞页面渲染?
Nuxt 动态页面渐进加载大量API数据解决方案
问题根源
你当前的代码会等待整个API请求完成后才一次性赋值给this.models,导致页面必须等11秒加载完所有数据才会渲染,出现长时间空白。要实现渐进加载,核心是让页面能逐步获取并渲染数据,而非等待全部请求完成。
方案一:后端分页+前端分批加载(最通用)
如果后端支持修改,优先把API改成分页接口,前端先加载第一页数据渲染,再异步加载剩余页面。
data() { return { models: [], currentPage: 1, totalPages: 0, isLoading: false } }, async fetch() { const path = this.$nuxt.context.route.path // 先加载第一页,优先渲染 const firstPageRes = await axios.get(`/api${path}?page=1&pageSize=100`, { headers: { 'X-AUTH-TOKEN': process.env.SECURE_TOKEN, 'Content-Type': 'application/json' } }) this.models = firstPageRes.data.content this.totalPages = firstPageRes.data.totalPages // 后台加载剩余页面 this.loadRemainingPages() }, methods: { async loadRemainingPages() { this.isLoading = true for (let page = 2; page <= this.totalPages; page++) { try { const res = await axios.get(`/api${this.$nuxt.context.route.path}?page=${page}&pageSize=100`, { headers: { 'X-AUTH-TOKEN': process.env.SECURE_TOKEN, 'Content-Type': 'application/json' } }) // 合并数据,触发页面实时更新 this.models = [...this.models, ...res.data.content] // 可选:添加延迟避免请求过于密集 await new Promise(resolve => setTimeout(resolve, 300)) } catch (err) { console.error('分页加载失败:', err) break } } this.isLoading = false } }, fetchOnServer: true // 服务端预渲染第一页,提升首屏速度
方案二:流式响应处理(需API支持分块传输)
如果API支持Transfer-Encoding: chunked分块返回数据,可以用Axios流式响应,边接收边渲染。
async fetch() { const path = this.$nuxt.context.route.path this.models = [] const response = await axios.get(`/api${path}`, { headers: { 'X-AUTH-TOKEN': process.env.SECURE_TOKEN, 'Content-Type': 'application/json' }, responseType: 'stream' // 开启流式响应 }) let buffer = '' // 监听分块数据 response.data.on('data', chunk => { buffer += chunk.toString() // 假设API按行返回单个数据项(需根据实际返回格式调整) const lines = buffer.split('\n') buffer = lines.pop() // 保留最后不完整的行 lines.forEach(line => { if (line.trim()) { try { const item = JSON.parse(line) this.models.push(item) // 逐步添加,页面实时更新 } catch (err) { console.error('数据解析错误:', err) } } }) }) // 处理最后剩余的内容 response.data.on('end', () => { if (buffer.trim()) { try { const item = JSON.parse(buffer) this.models.push(item) } catch (err) {} } }) }, fetchOnServer: false // 流式处理暂不建议在服务端启用
方案三:分批渲染完整数据(后端无法修改时)
如果只能拿到完整的大JSON,可在获取全部数据后,分批将数据注入models,利用Vue响应式特性逐步渲染。
async fetch() { const path = this.$nuxt.context.route.path this.models = [] const res = await axios.get(`/api${path}`, { headers: { 'X-AUTH-TOKEN': process.env.SECURE_TOKEN, 'Content-Type': 'application/json' } }) const allItems = res.data.content const batchSize = 100 // 每次渲染100条 let currentIndex = 0 const renderBatch = () => { const endIndex = Math.min(currentIndex + batchSize, allItems.length) this.models.push(...allItems.slice(currentIndex, endIndex)) currentIndex = endIndex // 用requestAnimationFrame避免阻塞UI线程 if (currentIndex < allItems.length) requestAnimationFrame(renderBatch) } renderBatch() }, fetchOnServer: true
内容的提问来源于stack exchange,提问作者J.O
相关产品推荐
相关产品推荐

