当前位置:网站首页>Nuxt - auto generate dynamic route bug

Nuxt - auto generate dynamic route bug

2022-06-23 01:31:00 hhzzcc_

The company needs to start a new ssr project , Just choose nuxt build , The construction process has also stepped on many pits , Write another article later when you have time nuxt Pit points and development considerations , Today is about nuxt Automatic generation router.js One of the bug( It can be directly pulled to the end to show the picture ), And the process of finding the cause through source code analysis . To tell you the truth, I feel that the function of automatically generating routes is a bit weak. Why not expand it here , Go straight to the point .

nuxt There is a function of automatically generating routes or dynamic routes , Here is an example from the official website

project pages File structure under :

pages/
--| _slug/
-----| comments.vue
-----| index.vue
--| users/
-----| _id.vue
--| index.vue

Will be generated automatically route

router: {
  routes: [
    {
      name: 'index',
      path: '/',
      component: 'pages/index.vue'
    },
    {
      name: 'users-id',
      path: '/users/:id?',
      component: 'pages/users/_id.vue'
    },
    {
      name: 'slug',
      path: '/:slug',
      component: 'pages/_slug/index.vue'
    },
    {
      name: 'slug-comments',
      path: '/:slug/comments',
      component: 'pages/_slug/comments.vue'
    }
  ]
}

The conclusion is

  • Path is /pages/a/_id.vue, It is automatically processed into a dynamic route with optional parameters /pages/a/:id?

  • Path is /pages/a/_id/index.vue, It is automatically processed into a dynamic route with mandatory parameters /pages/:id

  • Path is /pages/a/index.vue, Automatic processing into normal routes /pages/a

It is very simple to use , Later, I found that there was bug

pages/
--| order/
-----| index.vue
--| order-detail/
-----| _id.vue

Above directory , According to the rule, two dynamic routes should be generated, namely ( Others are omitted here for simplicity name、component Wait for related fields )

routes: [    { path: '/order' },    { path: '/order-detail/:id?' }]

But it produced

routes: [    { path: '/order' },    { path: '/order-detail/:id' }]

id hinder ? Be missing ,baidu、google Didn't find the answer , ok , Start skimming the source code , Download the project , Found his way to generate routes , stay /packages/utils/src/route.js Medium createRoutes Method

export const createRoutes = function createRoutes ({
     files,  srcDir,   pagesDir = '',  routeNameSplitter = '-',  supportedExtensions = ['vue', 'js'],  trailingSlash}) {
     ...}

The main concern here files Parameters , The whole process can be summarized as getting pages Save the file directory under to files Array , Passed to the current method for processing into the final generated route surface . For example, the above generates files The array value is

[  'pages/order/index.vue',  'pages/order-detail/_id.vue']

nuxt They will be dealt with first , Generate a preliminary route surface , as follows :

routes: [  {
       path: '/order',    name: 'order'  },  {
       path: '/order-detail/:id?',    name: 'order-detail-id'  }]

then nuxt I will deal with this again routes. Traverse the entire newly generated routes, Will include index.vue perhaps index.js The file path of is / Division , And remove the file suffix , Last push To routesIndex In a two-dimensional array , like this (order Folder containing index.vue So it will be push go in )

[  ['page', 'order', 'index']]

And then put path Median zone ? Of route They are generating paths Array and names Array , The generation rules are as follows :

route.path.split('/') Divided into paths Array

['page', 'order-detail', '_id?']

route.name.split('-') Divided into names Array

['page', 'order', 'detail', 'id']

Then do the third treatment , loop routes Array , Take each one ? Of route And again routesIndex Each item of the array is compared in a loop , hypothesis routesIndex The cycle term of is r, find r in index Index of a string i, The figure represents the index i by 2

// r Array , index The string index is 2, therefore i by 2['page', 'order', 'index']
// paths Array ['page', 'order-detail', '_id?']

If i Less than paths Array , Then execute the loop , Cycle neutralization names Do the matching , If the former i - 1 The contents of the items are all equal , Will paths The last item of ? Get rid of

if (i < paths.length) {
     for (let a = 0; a <= i; a++) {
             if (a === i) {
               paths[a] = paths[a].replace('?', '');          }          //  Meet and names The unequal items in are directly interrupted           if (a < i && names[a] !== r[a]) {
               break          }  }}

So why nuxt To do this step , Because it is mentioned above ,nuxt You need to support the generation of belts ? Dynamic routing for , At the same time, it is also necessary to support without ? Dynamic routing for , So he will first turn all dynamic routes into bands ? Of , Then do the processing through the above loop , Will and index File level with ? Remove the route of ?. Here's the problem ,order-detail stay names The array will be disassembled into order and detail, The above loop will not jump out , So the question mark is removed at the end of the run .

// order-detail Corresponding names['pages', 'order', 'detail', '_id']
// order-detail Corresponding paths['pages', 'order-detail', '_id?']
// order Corresponding routeIndex, index The index for 2,  also index Previous items and names just //  One-to-one correspondence , So it will go all the way to the end , In the end paths[2] Of ? Get rid of ['pages', 'order', 'index']

Post the core source code , You can go if you are interested nuxt github Take a look at it

routes.forEach(route => {
     // ... Omit   //  If it's a belt ? Of route and routesIndex compare   if (route.path.includes('?')) {
       routesIndex.forEach(r => {
         //  find index The index of i      const i = r.indexOf('index');      if (i < paths.length) {
           for (let a = 0; a <= i; a++) {
             //  Loop to the last item , eliminate ?          if (a === i) {
               paths[a] = paths[a].replace('?', '');          }          //  Meet and names The unequal items in are directly interrupted           if (a < i && names[a] !== r[a]) {
               break          }        }      }    });  }});

Post two visual pictures , This will trigger bug, Generate route Medium ? be without

 

It won't change to this

 

So how to avoid it ? Here are also two points

  • Dynamic route file naming needs to be accompanied by - when ,- The previous string should not contain index Duplicate file name for , For example, above order and order-detail, The name can be adjusted to orders and order-detail.

  • More extreme , Rewrite a copy directly route, from nuxt.config.js Introduction in , overwrite nuxt Self generated routes.

Conclusion :

I have time to nuxt The team asked issue

原网站

版权声明
本文为[hhzzcc_]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202220516248690.html