You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 13:25:15