admin管理员组

文章数量:1394984

I have three routes, /login, /signup and /forgot and their corresponding ponents which only contain the basic forms you'd expect. I would like those ponents to be contained within a landing page ponent without having to put my landing page logic within my three ponents because that would reload the container and my transitions wouldn't show.

My landing page has something like this going on

<h1>Wele to my web app</h1>
<transition name="slide" mode="">
   <router-view></router-view>
<transition>

routes.js looks like this

import SignUp from './ponents/SignUp';
import SignIn from './ponents/SignIn';
import Forgot from './ponents/Forgot';
export const routes = [
    { path: '/signup', ponent: SignUp },
    { path: '/login', ponent: SignIn },
    { path: '', ponent: SignIn },
    { path: '/forgot', ponent: Forgot }
];

Would I need some intermediary hidden route or something? Or would I only wrap the container based on conditional logic in App.vue (which, to me, doesn't seem like good practice)?

I have three routes, /login, /signup and /forgot and their corresponding ponents which only contain the basic forms you'd expect. I would like those ponents to be contained within a landing page ponent without having to put my landing page logic within my three ponents because that would reload the container and my transitions wouldn't show.

My landing page has something like this going on

<h1>Wele to my web app</h1>
<transition name="slide" mode="">
   <router-view></router-view>
<transition>

routes.js looks like this

import SignUp from './ponents/SignUp';
import SignIn from './ponents/SignIn';
import Forgot from './ponents/Forgot';
export const routes = [
    { path: '/signup', ponent: SignUp },
    { path: '/login', ponent: SignIn },
    { path: '', ponent: SignIn },
    { path: '/forgot', ponent: Forgot }
];

Would I need some intermediary hidden route or something? Or would I only wrap the container based on conditional logic in App.vue (which, to me, doesn't seem like good practice)?

Share Improve this question asked Mar 19, 2017 at 14:16 Mathieu BertinMathieu Bertin 4657 silver badges19 bronze badges
Add a ment  | 

5 Answers 5

Reset to default 4

In router.js you can send the currentComponent as a props,

import landingPage from './ponents/LandingPage';
export const routes = [
    { path: '/signup', ponent: landingPage, props: { currentComponent: 'SignUp' } },
    { path: '/login', ponent: landingPage, props: { currentComponent: 'SignIn' } },
    { path: '', ponent: landingPage, props: { currentComponent: 'SignIn' } },
    { path: '/forgot', ponent: landingPage, props: { currentComponent: 'Forgot' } }
];

and consider the landing page as a ponent (LandingPage.vue)

<template>    
<h1>Wele to my web app</h1>
    <transition name="slide" mode="">
       <ponent :is="currentComponent">
    <transition>
</template>

<script>
import SignUp from './ponents/SignUp';
import SignIn from './ponents/SignIn';
import Forgot from './ponents/Forgot';
export default {
  ponents: ['SignUp', 'SignIn', 'Forgot'],
  props: ['currentComponent']
}
</script>

I was able to make this work using named nested <router-view> elements like this

routes.js

import SignUp from './ponents/SignUp';
import SignIn from './ponents/SignIn';
import Forgot from './ponents/Forgot';
import RegistrationWrapper from './ponents/RegistrationWrapper';

export const routes = [{
    path: '/signup',
    ponents: {
        default: SignUp,
        'wrapper': RegistrationWrapper
    }
}, {
    path: '/login',
    ponents: {
        default: SignIn,
        'wrapper': RegistrationWrapper
    }
}, {
    path: '/forgot',
    ponents: {
        default: Forgot,
        'wrapper': RegistrationWrapper
    }
}, {
    path: '/',
    ponents: {
        default: SignIn,
        'wrapper': RegistrationWrapper
    }
}];

RegistrationWrapper.vue

<template>
   <h1>Wele to my web app</h1>
   <transition name="slide" mode="">
      <slot></slot>
   <transition>
<template>

and my App.vue looks like this

<template>
    <div>
       <router-view name="wrapper">
          <router-view></router-view>
       </router-view>
   </div>
</template>

The only downside to this that I can see is the fact that I now have to supply a wrapper to all my routes which will probably get redundant. How would I detect if wrapper was supplied or not in App.vue? Also, is there another downside I'm not seeing here?

Nested Routes should take care of your problem nicely. Here is an example from the docs:

Here in following ponent, User part is same in both the routes, internal content needs to be different in these routes:

/user/foo/profile                     /user/foo/posts
+------------------+                  +-----------------+
| User             |                  | User            |
| +--------------+ |                  | +-------------+ |
| | Profile      | |  +------------>  | | Posts       | |
| |              | |                  | |             | |
| +--------------+ |                  | +-------------+ |
+------------------+                  +-----------------+

<router-view> is a top-level outlet. It renders the ponent matched by a top level route. Similarly, a rendered ponent can also contain its own, nested <router-view>. For example, if we add one inside the User ponent's template:

const User = {
  template: `
    <div class="user">
      <h2>User {{ $route.params.id }}</h2>
      <router-view></router-view>
    </div>
  `
}

To render ponents into this nested outlet, we need to use the children option in VueRouter constructor config:

const router = new VueRouter({
  routes: [
    { path: '/user/:id', ponent: User,
      children: [
        {
          // UserProfile will be rendered inside User's <router-view>
          // when /user/:id/profile is matched
          path: 'profile',
          ponent: UserProfile
        },
        {
          // UserPosts will be rendered inside User's <router-view>
          // when /user/:id/posts is matched
          path: 'posts',
          ponent: UserPosts
        }
      ]
    }
  ]
})

Note that nested paths that start with / will be treated as a root path. This allows you to leverage the ponent nesting without having to use a nested URL.

For vue-router 4 it's more easy in this way:

<router-view v-slot="{ Component }">
  <Wrapper>
    <ponent :is="Component" />
  </Wrapper>
</router-view>

Actually the answer has been in the docs all along:

Note that nested paths that start with / will be treated as a root path. This allows you to leverage the ponent nesting without having to use a nested URL.

Although a bit hard to wrap your head around, it means you can write something like this:

 {
    path: '/login',
    ponent: () => import ('@/pages/SignInSignUpWrapper.vue'),
    children: [
      {
        path: '',
        ponent: () => import ('@/pages/SignIn.vue')
      },
      {
        path: '/signup',
        ponent: () => import ('@/pages/SignUp.vue')
      }
    ]
  },

This will produce only two routes: /login and /signup. They'll both have SignInSignUpWrapper ponent as parent, and the ponents will render in SignInSignUpWrapper's <route-view>'s slot

本文标签: javascriptWrapping three specific routes with the same component in VueJSStack Overflow