Vue-router: Ability to have one root `router-view` both for regular and child routes

Created on 16 May 2017  路  10Comments  路  Source: vuejs/vue-router

What problem does this feature solve?

Fallback to parent's parent router-view if no <router-view></router-view>
element was provided inside it.
To explain better the idea behind the feature request lets follow the example.

Let's imagine we have a router with following routing map

[
    // other stuff...

    {
        // Note here how we've omitted `component` field
        path: '/me',
        children: [
            {
                path: '',
                component: BaseUserProfileView,
                children: [
                    {
                        path: '',
                        component: UserRecentActivityView
                    },

                    {
                        path: '/posts',
                        component: UserPostsView
                    },
                ]
            },

            {
                path: '/settings',
                component: UserSettingsView
            }
        ]
    }
]

And the following view components

const BaseProfileView = {
    template:`
        <div class="base-profile-view">
            <router-view></router-view>
        </div>
    `
}

const UserRecentActivityView = {
    template: `
        <div>/me</div>
    `
}

const UserPostsView = {
    template: `
        <div>/me/posts</div>
    `
}

const UserSettingsView = {
    template: `
        <div>/me/settings</div>
    `
}

And finally the application with following structure

const App = {
    template: `
        <div>
            <router-view></router-view>
        </div>
    `
}

Want I'd like to see to be rendered

<!--
  /me
  /me/posts
  etc.
-->
<div>
    <div class="base-profile-view">
        <div>...</div>
    </div>
<div>

<!-- /me/settings -->
<div>
    <div>/me/settings</div>
</div>

But nowdays router just ignoring the case and doesn't render any routes
in such way.

What does the proposed API look like?

There is no any programmatic changes to router itself, but an option.
If there was no root component for current child tree go upper until
we found <router-view></router-view> and render inside it the current
matched component of the tree.

Most helpful comment

@vanesyan you may have missed it, but nuxt (I don't know whether this convention was inherited from next or not) treats a folder differently depending on whether there is a file along with the folder with the same name. If there is, then it creates subroutes, if there isn't, then it creates flat routes.

Another part of what you are trying to do (showing/not showing parts for different routes) can be resolved with layouts (e.g. <component :is="$route.meta.layout">).

All 10 comments

I'm not sure to get the point. A route should always map to a component (or redirect). Can't you do

[
  {
    path: '/me',
    component: BaseUserProfileView,
    children: [
      {
        path: '',
        component: UserRecentActivityView
      },

      {
        path: '/posts',
        component: UserPostsView
      },
    ]
  },

  {
    path: '/me/settings',
    component: UserSettingsView
  }
]

Yeah, that is the good way if you write applications part by hand, but now imagine that you write framework something similar to next.js (React based framework to create application from dir. by Zeit). We need to generate paths for router based on content in pages folder. You have two options: the first one is to add each route to main routes array:

[
    {
        path: '/me',
        component: () => import('/path/to/app/pages/me/index.vue')
    },

    {
        path: '/me/posts',
        component: () => import('/path/to/app/pages/me/posts.vue')
    },

    {
        path: '/me/settings',
        component: () => import('/path/to/app/pages/me/settings.vue')
    }

    // etc.
]

But now we have lost the ability of sub <router-view></router-view> points.

The second one option is to set children routes (which more is correct IMO), but now we should introduce <router-view></router-view> (what nuxt.js does nowdays) in each parent route, which is fine, until we want to render specific view component that should be treated as root route, e.i. as in previous example of initial issue comment. This can be worked around with code you've provided, but the realization of it in terms of framework would be too complex, I think.

I still don't get what prevents you from adding a component to your /me route that is just

<router-view/>

This can be worked around with code you've provided, but the realization of it in terms of framework would be too complex, I think

To be honest, I don't think it's that complex: given your routes object you can check if a component is not provided and make the transformation

Imagine that both /me and /me/post should has header caption with user's profile info, but /me/settings should be rendered without it, so the plan is to put both /me and /me/post under the same parent route with set component to basic layout for both of 'em and put /me/settings outside of it.

I still don't get what prevents you from adding a component to your /me route that is just

<router-view></router-view>

To make it simpler to write views for end user

To be honest, I don't think it's that complex: given your routes object you can check if a component is
not provided and make the transformation

Sorry, but I don't clearly understand this part, can you elaborate on it, please :)

To make it simpler to write views for end user

Sorry, but it's really simple already and I don't think it's worth adding this feature to only omit the component option in the route config

Sorry, but I don't clearly understand this part, can you elaborate on it, please :)

You can write a function that returns a new routes array that will check every route and see if it doesn't have component options to _move up_ their children

@vanesyan you may have missed it, but nuxt (I don't know whether this convention was inherited from next or not) treats a folder differently depending on whether there is a file along with the folder with the same name. If there is, then it creates subroutes, if there isn't, then it creates flat routes.

Another part of what you are trying to do (showing/not showing parts for different routes) can be resolved with layouts (e.g. <component :is="$route.meta.layout">).

I wrote a plugin for this problem;

https://github.com/abdullah/safranbolu

@abdullah you did not provided any sort of documentation on how to use it

@isneezy Can you help me to write a small documentation?

I've already written a small comment blocks but I don't have enough time to write more.

https://github.com/abdullah/safranbolu/blob/master/safranbolu.js

Was this page helpful?
0 / 5 - 0 ratings