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

Vue新手求助:如何通过Axios调用外部API匹配动态路由获取JSON数据?

嘿,作为Vue新手能上手SPA+动态路由+Axios的组合已经超棒啦!看你给出的代码片段,应该是想实现单篇文章详情页,同时获取上下篇文章的数据对吧?我来帮你把这段代码补全并优化,让它能完美跑起来~

完整的组件实现代码

下面是包含完整逻辑的.vue组件,涵盖了动态路由参数获取、文章数据请求、上下篇导航以及错误处理:

<template>
  <div class="post-detail">
    <!-- 加载状态提示 -->
    <div v-if="!post" class="loading">加载中...</div>
    
    <!-- 文章内容展示 -->
    <div v-else class="post-content">
      <h1>{{ post.title }}</h1>
      <p class="post-body">{{ post.body }}</p>
      
      <!-- 上下篇导航 -->
      <div class="post-nav">
        <button 
          v-if="prevPost" 
          @click="navigateToPost(prevPost.id)"
          class="nav-btn prev-btn"
        >
          ← 上一篇: {{ prevPost.title }}
        </button>
        <button 
          v-if="nextPost" 
          @click="navigateToPost(nextPost.id)"
          class="nav-btn next-btn"
        >
          下一篇: {{ nextPost.title }} →
        </button>
      </div>
    </div>
  </div>
</template>

<script>
import axios from 'axios'

export default {
  data() {
    return {
      post: null,
      nextPost: null,
      prevPost: null,
      totalPosts: 0,
      endpoint: 'https://jsonplaceholder.typicode.com/posts/'
    }
  },
  methods: {
    // 获取总文章数(用于判断上下篇边界)
    async fetchTotalPosts() {
      try {
        const response = await axios.get(this.endpoint)
        this.totalPosts = response.data.length
      } catch (error) {
        console.error('获取总文章数失败:', error)
      }
    },
    // 获取当前文章详情
    async fetchCurrentPost(postId) {
      try {
        console.log('当前文章ID:', postId)
        const response = await axios.get(`${this.endpoint}${postId}`)
        this.post = response.data
        // 拿到当前文章后,立即获取上下篇
        this.fetchNavPosts(postId)
      } catch (error) {
        console.error('获取文章详情失败:', error)
        // 可以在这里处理404场景,比如跳转到404页面
        // this.$router.push('/404')
      }
    },
    // 获取上下篇文章数据
    async fetchNavPosts(currentId) {
      const numId = parseInt(currentId)
      
      // 获取上篇文章(仅当当前ID大于1时)
      if (numId > 1) {
        try {
          const prevResponse = await axios.get(`${this.endpoint}${numId - 1}`)
          this.prevPost = prevResponse.data
        } catch (error) {
          console.error('获取上篇文章失败:', error)
        }
      } else {
        this.prevPost = null
      }
      
      // 获取下篇文章(仅当当前ID小于总文章数时)
      if (numId < this.totalPosts) {
        try {
          const nextResponse = await axios.get(`${this.endpoint}${numId + 1}`)
          this.nextPost = nextResponse.data
        } catch (error) {
          console.error('获取下篇文章失败:', error)
        }
      } else {
        this.nextPost = null
      }
    },
    // 跳转到目标文章页面
    navigateToPost(postId) {
      this.$router.push(`/posts/${postId}`)
    }
  },
  created() {
    // 组件初始化时,获取当前文章和总文章数
    const currentPostId = this.$route.params.id
    this.fetchCurrentPost(currentPostId)
    this.fetchTotalPosts()
  },
  watch: {
    // 监听路由参数变化,实现页面无刷新切换文章
    '$route.params.id'(newPostId) {
      // 重置数据,避免旧内容残留
      this.post = null
      this.prevPost = null
      this.nextPost = null
      // 重新获取新文章数据
      this.fetchCurrentPost(newPostId)
    }
  }
}
</script>

<style scoped>
.post-detail {
  max-width: 800px;
  margin: 2rem auto;
  padding: 0 1.5rem;
}
.loading {
  font-size: 1.2rem;
  text-align: center;
  padding: 3rem 0;
}
.post-content h1 {
  color: #2c3e50;
  border-bottom: 1px solid #eee;
  padding-bottom: 0.5rem;
}
.post-body {
  line-height: 1.6;
  color: #34495e;
  margin: 1.5rem 0;
}
.post-nav {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
}
.nav-btn {
  padding: 0.6rem 1.2rem;
  border: none;
  border-radius: 4px;
  color: white;
  cursor: pointer;
  transition: background-color 0.2s;
}
.prev-btn {
  background-color: #3498db;
}
.prev-btn:hover {
  background-color: #2980b9;
}
.next-btn {
  background-color: #2ecc71;
}
.next-btn:hover {
  background-color: #27ae60;
}
</style>
关键细节说明
  • 动态路由参数获取:通过this.$route.params.id拿到当前路由的文章ID,这是Vue动态路由的核心用法。
  • Async/Await语法:用它替代了嵌套的.then(),让异步代码的逻辑更清晰,新手也更容易追踪执行流程。
  • 错误处理:每个Axios请求都加了try/catch,方便调试请求失败的情况,也能给用户更友好的反馈。
  • 路由监听:添加了watch监听路由参数变化,用户点击上下篇按钮时,页面不用刷新就能加载新的文章内容。
  • 边界判断:根据总文章数判断上下篇是否存在,避免请求不存在的文章ID(比如ID=0或ID=101)。
配套的路由配置

别忘了在你的路由文件(通常是src/router/index.js)里配置对应的动态路由:

import { createRouter, createWebHistory } from 'vue-router'
import PostDetail from '../views/PostDetail.vue' // 你的文章详情组件路径

const routes = [
  // 其他路由配置...
  {
    path: '/posts/:id',
    name: 'PostDetail',
    component: PostDetail,
    // 可以添加路由守卫,比如验证ID是否为数字
    beforeEnter: (to, from, next) => {
      if (!isNaN(to.params.id)) {
        next()
      } else {
        next('/404')
      }
    }
  }
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

export default router

内容的提问来源于stack exchange,提问作者Tom

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:41:05