vue.js 在Nuxt3中间件中动态添加路由

kkih6yb8  于 2023-02-13  发布在  Vue.js
关注(0)|答案(2)|浏览(997)

我有一个Nuxt3项目,我想基于API调用向数据库添加新的路由。例如,假设用户导航到/my-product-1。路由中间件将查看数据库,如果它找到一个条目,它将返回应该呈现product页面(而不是类别页面,例如)。
这是我想到的

export default defineNuxtPlugin(() => {

    const router = useRouter()

    addRouteMiddleware('routing', async (to) => {
        if (to.path == '/my-awesome-product') {
            router.addRoute({
                component: () => import('/pages/product.vue'),
                name: to.path,
                path: to.path
            })
            
            console.log(router.hasRoute(to.path))   // returns TRUE
        }
    }, { global: true })

})

为了简单起见,我从这个例子中排除了API调用。上面的解决方案可以工作,但在路由的初始加载时不行。路由确实被添加到了Vue路由器中(即使是在第一次访问时),但是,当我直接访问该路由时,它显示了404,只有当我没有在客户端上重新加载页面时,它才会在第二次导航到它时显示正确的页面。
我猜这和路由器没有更新有关...我在GitHub的一个问题中发现了下面的例子,但是,我不能让它在Nuxt3中工作,因为(据我所知)它没有提供next()方法。当我试图在router.addRoute行下面添加router.replace(to.path)时,我陷入了一个无限重定向循环。

// from https://github.com/vuejs/vue-router/issues/3660
// You need to trigger a redirect to resolve again so it includes the newly added

route:
let hasAdded = false;
router.beforeEach((to, from, next) => {
  if (!hasAdded && to.path === "/route3") {
    router.addRoute(
      {
        path: "/route3",
        name: "route3",
        component: () => import("@/views/Route3.vue")
      }
    );
    hasAdded = true;
    next('/route3');
    return;
  }
  next();
});

请问我如何解决此问题?
编辑:根据一个建议,我尝试使用navigateTo()来替换Vue Router中的next()方法,但是,这在第一次导航到路线时也不起作用。

let dynamicPages: { path: string, type: string }[] = []

export default defineNuxtRouteMiddleware((to, _from) => {
    const router = useRouter()

    router.addRoute({
        path: to.path,
        name: to.path,
        component: () => import ('/pages/[[dynamic]]/product.vue')
    })
    
    if (!dynamicPages.some(route => route.path === to.path)) {
        dynamicPages.push({
            path: to.path,
            type: 'product'
        })
        return navigateTo(to.fullPath)
    }
})

我也想出了这个代码(它的工作方式就像我想要的),但是,我不知道这是否是最好的解决方案。

export default defineNuxtPlugin(() => {

    const router = useRouter()
    
    let routes = []

    router.beforeEach(async (to, _from, next) => {

        const pageType = await getPageType(to.path) // api call
        
        if (isDynamicPage(pageType)) {
            router.addRoute({
                path: to.path,
                name: to.path,
                component: () => import(`/pages/[[dynamic]]/product.vue`),
            })
            
            if (!routes.some(route => route.path === to.path)) {
                routes.push({
                    path: to.path,
                    type: pageType,
                })
                next(to.fullPath)
                return
            }
        }
        
        next()
    })
})
5f0d552i

5f0d552i1#

我建议您在/page目录结构中使用动态路由-https://nuxt.com/docs/guide/directory-structure/pages#dynamic-routes
[slug]的概念完全是为你的使用情况设计的。你不需要事先知道所有可能的路径。你只需要提供一个占位符,Nuxt就会在运行时负责解析。

k0pti3hp

k0pti3hp2#

如果您坚持在每次路由更改之前解析调用的方法,那么您正在寻找的用于next()方法的Nuxt替代方法是navigateTohttps://nuxt.com/docs/api/utils/navigate-to
我建议你使用路由中间件,把你的逻辑放到/middleware/routeGuard.global.ts中,它会在每次路由解析事件时自动执行,文件将包含:

export default defineNuxtRouteMiddleware((to, from) => {

  // your route-resolving logic you wanna perform

  if ( /* navigation should happen */ {
    return navigateTo( /* your dynamic route */ )
  }
  // otherwise do nothing - code will flow and given to.path route will be resolved
})

编辑:但是,这仍然需要/pages目录中的内容或通过Vue路由器创建的一些路由。否则navigateTo将失败,因为没有路由可供使用。

下面是一个可能的方法示例:
https://stackblitz.com/edit/github-8wz4sj
基于从API返回的pageType,Nuxt路由守卫可以动态地将原始URL重新路由到特定的slug页面。

相关问题