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
相关产品推荐
相关产品推荐

