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

Nuxt动态路由添加标题优化SEO及分类页URL处理问询

问题一:产品页URL添加产品标题Slug

要把产品页URL从example.com/product/1改成example.com/product/1/nike-shoe,可以通过路由参数扩展+动态更新URL的方式实现,步骤如下:

1. 扩展路由支持可选Slug参数

Nuxt默认的动态路由_id.vue只支持/product/:id,我们需要让它同时支持带slug的路径。在nuxt.config.js里通过extendRoutes修改路由规则:

export default {
  extendRoutes(routes, resolve) {
    // 找到原产品页路由
    const productRoute = routes.find(route => route.name === 'product-id')
    if (productRoute) {
      // 修改路径,添加可选的slug参数(?表示可选)
      productRoute.path = '/product/:id/:slug?'
      // 保持组件指向原页面
      productRoute.component = resolve(__dirname, 'pages/product/_id.vue')
    }
  }
}

2. 获取产品数据后动态更新URL

在_id.vue的fetch方法里,拿到产品数据后生成标准化slug(转小写、替换空格为横杠),如果当前URL没有slug,就用$router.replace更新URL(不会触发页面刷新):

async fetch(){ 
  let response = await this.axiosFetch(`product/${this.$route.params.id}`) 
  if(this.resOk(response.status)){ 
    if(this.notEmpty(response.data)){ 
      this.product = response.data 
      // 生成标准化的slug
      const slug = this.product.title.toLowerCase().replace(/\s+/g, '-')
      // 检查当前URL是否已有slug,无则更新
      if (!this.$route.params.slug) {
        this.$router.replace({
          name: 'product-id',
          params: {
            id: this.$route.params.id,
            slug: slug
          }
        }, () => {}, () => {}) // 第三个参数忽略重复导航报错
      }
    }
  }else{ 
    this.$nuxt.error({ statusCode: 404, message: "not found" }) 
  } 
},

这样处理后:

  • 用户访问/product/1会自动跳转到/product/1/nike-shoe
  • 直接访问带slug的URL也能正常加载页面
  • 所有产品页都会拥有SEO友好的URL

问题二:分类页URL添加分类标题Slug(保持同一页面)

原来的分类页用query传递catId,现在要改成路径式的slug(比如/category/electronics),同时不跳转页面,步骤如下:

1. 配置分类页路由支持Slug参数

同样在nuxt.config.js里扩展路由,让/category和/category/:catSlug都指向同一个页面组件:

export default {
  extendRoutes(routes, resolve) {
    // 移除默认的category路由(如果存在)
    const defaultCatRoute = routes.find(route => route.name === 'category' && route.path === '/category')
    if (defaultCatRoute) routes.splice(routes.indexOf(defaultCatRoute), 1)
    
    // 添加支持可选slug的分类路由
    routes.push({
      name: 'category',
      path: '/category/:catSlug?',
      component: resolve(__dirname, 'pages/category.vue')
    })
  }
}

2. 修改分类数据获取逻辑

需要根据路由的catSlug参数获取对应的分类ID,同时维护slug和分类ID的映射:

data() {
  return {
    catArray: [],
    slugToIdMap: {}, // 存储slug到分类ID的映射
    currentCatId: 0
  }
},
async fetch() {
  let initialCatId = 0
  // 如果URL有slug,先通过slug获取分类ID(假设后端提供根据slug查询分类的接口)
  if (this.$route.params.catSlug) {
    const catData = await this.$axios.$get(`category/slug/${this.$route.params.catSlug}`)
    if (catData) initialCatId = catData.id
  }

  // 加载分类数据
  const res = await this.$axios.$get(`category/${initialCatId}`)
  this.catArray.push(res)
  this.currentCatId = initialCatId

  // 构建slug-ID映射(假设分类数据里有children子分类列表)
  if (res.children) {
    res.children.forEach(child => {
      const slug = child.title.toLowerCase().replace(/\s+/g, '-')
      this.slugToIdMap[slug] = child.id
    })
  }
}

3. 点击子分类时更新URL

在子分类的点击事件里,生成对应slug并更新路由,同时加载子分类数据:

methods: {
  async onCategoryClick(childCat) {
    // 生成子分类的slug
    const slug = childCat.title.toLowerCase().replace(/\s+/g, '-')
    // 更新路由(不刷新页面)
    await this.$router.replace({
      name: 'category',
      params: { catSlug: slug }
    })
    
    // 加载子分类数据
    this.currentCatId = childCat.id
    const res = await this.$axios.$get(`category/${childCat.id}`)
    this.catArray.push(res)
    
    // 更新slug-ID映射
    if (res.children) {
      res.children.forEach(child => {
        const childSlug = child.title.toLowerCase().replace(/\s+/g, '-')
        this.slugToIdMap[childSlug] = child.id
      })
    }
  }
}

这样处理后:

  • 初始访问/category会加载父分类,URL保持不变
  • 点击子分类后,URL变成/category/electronics,页面不跳转,直接加载子分类内容
  • 直接访问带slug的URL能直接加载对应分类,SEO更友好

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 09:47:31