以下内容对我有用,但我不确定它是否与 Stack Overflow URL 结构的工作方式完全相同。
我正在使用async asyncData 从数据库中获取内容,您可以访问
context 和 redirect、req 和 res 作为参数,您可以执行 301 重定向。
首先我在我的文件夹中使用unknown dynamic nested routes,例如/pages/folder/_.vue。它将捕获所有路线,包括domain.com/folder/{id} 和domain.com/folder/{id}/{title}。
要获取请求的 url 中的 ID,您可以拆分 pathMatch 并获取第一个元素,例如 params.pathMatch.split('/')[0]。
然后我使用 id 从数据库中获取内容,在我的例子中是 Strapi。喜欢这个await $strapi.findOne('contentType', id)。
之后,我们可以像/folder/${data.id}/${data.slug} 这样创建我们想要的实际 URL。注意:data.slug 可以替换为data.title,可以转换为 URL 友好字符串。
最后我们可以将用户请求的 URL 与内容的实际 URL if(route.fullPath !== actualURL) 匹配,如果请求的 url 不一样,我们可以使用 redirect(301, actualURL) 执行重定向。
我的整个代码:
async asyncData({ redirect, req, route, app, $strapi, error, params }) {
try {
const recipeID = params.pathMatch.split('/')[0];
const matchingRecipe = await $strapi.findOne('recipes', recipeID);
const correctPath = `${app.localePath('recipes')}/${matchingRecipe.id}/${matchingRecipe.slug}`;
if(route.fullPath !== correctPath) {
console.log(`Redirect: ${route.fullPath} => ${correctPath}`);
redirect(301, correctPath);
}
return {
recipe: matchingRecipe
}
} catch(e) {
console.log(e)
error({ statusCode: e.statusCode, message: e.original });
}
},