Search code examples
nuxt.jsvue-routernuxt3.js

Dynamic routing in Nuxt3


How would you manage an url structure like the one below?

I am migrating a project to Nuxt3 and I would like to understand if I can avoid managing redirects.

/fashion blog category fashion

/fashion/page-3 blog category fashion page 3

/fashion/35/cool-article blog post from blog category fashion with id 35 and alias "cool-article"

The main problem I am encountering is that blog categories are dynamic, but there are also other dynamic routes and I don't want a general "catch all" vue file that handles everything, and I would like also to avoid loading all possible routes.


Solution

  • For the routes you've listed, I'd create following structure inside Nuxt's dedicated /page directory:

    -| pages/
    ---| [category]/
    ------| [item]/
    ---------| [alias].vue
    ------| page-[page].vue
    ------| index.vue
    
    1. /pages/[category]/index.vue would look like this:
    <template>
      <div>
       <CategoryShow :category="category" :page="1" />
      </div>
    </template>
    
    <script setup>
    const category = useRoute().params.category
    </script>
    

    This will trigger for /fashion route (page named "index" is always a default fallback if no other defined route matches). Inside Nuxt build-in useRoute() composable via its params array there is the current value of the dynamic parameter. Nuxt automatically fills this array based on parts of the route enclosed inside square brackets. The extracted value will be passed as a prop into dedicated /components/Category/Show.vue file. Here you would handle the displaying.

    I assumed a default value for "page". But it is also possible to make the prop optional inside the component and just omit it here.

    1. /pages/[category]/page-[page].vue will look quite the same, just it also handles the page:
    <template>
      <div>
       <CategoryShow :category="category" :page="page" />
      </div>
    </template>
    
    <script setup>
    const category = useRoute().params.category
    const page = useRoute().params.page
    </script>
    

    This will consume /fashion/page-3 route. In that case the value of category will be fashion and value of page would be 3.

    1. /pages/[category]/[item]/[alias].vue would be:
    <template>
      <div>
       <ArticleShow :item="item" />
      </div>
    </template>
    
    <script setup>
    const item = useRoute().params.item
    </script>
    

    I believe you only need item part of the route to identify and display the desired article, but written like this it will catch all possible routes like /fashion/35/cool-article. Params category and alias will be available, if you need them for some reason.

    This is how I would handle the given route examples. But since you mention "other dynamic routes", I am not sure, if it is the right approach. But I would generally try to fit all my content to match contents of /page directory, because like that Nuxt gives me powerful and quite complex routing out of the box with little-to-zero effort.

    If you need more, there is also useRouter() composbale, that wraps underying VueRouter and allows manual interaction with the routes.