如何使用vue.js和vue路由器实现当前路由子节点的子菜单 [英] How to implement sub menu of the current route's children with vue.js and vue router

查看:127
本文介绍了如何使用vue.js和vue路由器实现当前路由子节点的子菜单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在我的Vue应用程序上进行导航,使主菜单顶部填充所有根级别路径,如果路径有任何子级则使用侧边菜单。像这样:





我目前的设计主要有使用下面的路由器视图在顶部导航路由链接。我已经能够使侧边菜单工作,所以当我选择Travellers并正确更新组件/内容时它才显示出来。但是我无法正确路由,当我点击子菜单中的一个链接时,它不会附加到当前路径。因此,当我在 localhost / Traveler 时单击查看并单击查看时,网址将更改为 localhost / View / ,而不是本地主机/旅行者/视图即可。当我在子菜单中选择某些内容时,顶部菜单上的选择也会被取消选择。





我无法通过 localhost / Traveler / View 之类的内容访问这些页面 localhost / View



我开始重读有关



我只是不确定如何访问这些属性。



更新1/29/2019:



我发现你需要做的就是路径是使用 $ Route.matched [0] .path 你可以在这里了解更多。



现在我已经能够将菜单简化为这样的SFC:

 < template> 
< nav id =sidebar>
< div class =sidebar-header>
< h3> Bootstrap边栏< / h3>
< / div> $ router $。$ b< ul class = .matched [0]。路径)>
< li v-for =child in route.children>
< a class =nav-item:key =index>
< router-link:to =route.path +'/'+ child.pathexact-active-class =active>
< icon:icon =route.iconclass =mr-2/>< span> {{child.name}}< / span>
< / router-link>
< / a>
< / li>
< / ul>

< / nav>

< / template>

< script>
导出默认{
data(){
return {
}
}
}
< / script>

不包括CSS。



编辑:我现在把它作为我的首选答案,因为它允许我通过引用组件在任何地方使用侧边菜单。我不需要传递任何东西,它在任何地方工作。我确实喜欢digitaldrifter的回答,因为他有一个小提琴。


I'm trying to have the navigation on my Vue app to have a main menu up top populated by all the root level routes, and a side menu if the route has any children. Like so:

The current Design I have has the main navigation with routing links on the top with the router-view below. I have been able to get the side menu working so it it only shows up when I choose Travellers and updates the components/content correctly. However I'm having trouble routing things correctly, when I click on one of the links in the sub menu it does not append to the current path. So when I click on View when I'm in localhost/Traveler and click View the url changes to localhost/View/ instead of localhost/Traveler/View. Also the selection on the top menu gets unselected when I choose something in the child menu.

And I cannot get to the pages via something like localhost/Traveler/View only localhost/View

I started rereading the documentation on nested routes as I began making this post and I think I realized that I should be creating an new router at each level which is not something I have done in my code below.

I'm also not sure how to access the children of the current route. I've tried to display them like so:

  <h2>Route: {{ $route.name }}</h2>
  <ul id="example-1">
    <li v-for="child in $route.children">
      {{ child.name }}
    </li>
  </ul>

But I get nothing. Should they be passed as Params or something? Or are the not that easily accessible?

Any advice or help will be greatly appreciated.

Root

Contains top Menu-Nav with router links and router-view below.

<template>
  <div id="app" class="container-fluid">
    <div class="row">
      <div style="width:100%">
        <nav-menu params="route: route"></nav-menu>
      </div>

    </div>

    <div class="row">
      <div>
        <router-view></router-view>
      </div>
    </div>
  </div>
</template>
<script>
  import NavMenu from './nav-menu'

  export default {
    components: {
      'nav-menu': NavMenu
    },

    data() {
      return {}
    }
  }
</script>

Top Nav-Menu

Gets populated with the routes

<template>
  <nav class="site-header sticky-top py-1">
    <div class="container d-flex flex-column flex-md-row justify-content-between">
      <a class="nav-item" v-for="(route, index) in routes" :key="index">
        <router-link :to="{path: route.path, params: { idk: 1 }}" exact-active-class="active">
          <icon :icon="route.icon" class="mr-2" /><span>{{ route.display }}</span>
        </router-link>
      </a>
    </div>
  </nav>
</template>
<script>
  import { routes } from '../router/routes'

  export default {
    data() {
      return {
        routes,
        collapsed: true
      }
    },
    methods: {
      toggleCollapsed: function (event) {
        this.collapsed = !this.collapsed
      }
    }
  }
</script>

Traveler Page/View

Currently the Traveller Page which has a side bar menu and another router view for the content:

<template>
  <div id="app" class="container-fluid">
    <div class="wrapper">
      <traveler-menu params="route: route"></traveler-menu>

      <div id="content">
        <router-view name="travlerview"></router-view>
        </div>
      </div>
    </div>
</template>
<script>
  import TravelerMenu from './traveler-menu'
  export default {
    components: {
      'traveler-menu': TravelerMenu
    },
    data() {
      return {}
    }
  }
</script>

Side Bar/ Traveler Menu

<template>
    <nav id="sidebar">
      <div class="sidebar-header">
        <h3>Route's Children:</h3>
      </div>

      <ul class="list-unstyled components">
        <li>
          <a class="nav-item" v-for="(route, index) in travelerroutes" :key="index">
            <router-link :to="{path: route.path, params: { idk: 1 }}" exact-active-class="active">
              <icon :icon="route.icon" class="mr-2" /><span>{{ route.display }}</span>
            </router-link>
          </a>
        </li>
      </ul>

    </nav>

</template>

<script>
    import { travelerroutes } from '../../router/travelerroutes'
    export default {
    data() {
      console.log(travelerroutes);
        return {
          travelerroutes,
          collapsed: true
        }
      },
      methods: {
        toggleCollapsed: function (event) {
          this.collapsed = !this.collapsed
        }
      }
    }
</script>

Routes

import CounterExample from 'components/counter-example'
import FetchData from 'components/fetch-data'
import HomePage from 'components/home-page'
import TestPage from 'components/test-page'
import Travelers from 'components/Traveler/traveler-root'
import { travelerroutes } from './travelerroutes'

export const routes = [
  { name: 'home', path: '/', component: HomePage, display: 'Home', icon: 'home' },
  { name: 'counter', path: '/counter', component: CounterExample, display: 'Counter', icon: 'graduation-cap' },
  { name: 'fetch-data', path: '/fetch-data', component: FetchData, display: 'Fetch data', icon: 'list' },
  { name: 'test-page', path: '/test-page', component: TestPage, display: 'Test Page', icon: 'list' },
  {
    name: 'traveler-root', path: '/traveler', component: Travelers, display: 'Travelers', icon: 'list', children: travelerroutes
  }
]

Traveler Routes (travelerroutes.js)

import TestPage from 'components/test-page'
import ViewTravelers from 'components/Traveler/TravelerPages/view-travelers'

export const travelerroutes = [{
  name: 'View',
  path: '/View',
  display: 'View', icon: 'list',
  components: {
    travlerview: TestPage
  }
},
  {
    name: 'Create',
    path: '/Create',
    display: 'Create', icon: 'list',
    components: {
      travlerview: ViewTravelers
    }
  },
  {
    name: 'Edit',
    path: '/Edit',
    display: 'Edit', icon: 'list',
    components: {
      travlerview: ViewTravelers
    }
  }];

router/index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import { routes } from './routes'

Vue.use(VueRouter)

let router = new VueRouter({
  mode: 'history',
  routes
})

export default router

app.js

import Vue from 'vue'
import axios from 'axios'
import router from './router/index'
import store from './store'
import { sync } from 'vuex-router-sync'
import App from 'components/app-root'
import { FontAwesomeIcon } from './icons'

// Registration of global components
Vue.component('icon', FontAwesomeIcon)

Vue.prototype.$http = axios

sync(store, router)

const app = new Vue({
  store,
  router,
  ...App
})

export {
  app,
  router,
  store
}

Let me know if you you need anymore details, context or code.

解决方案

I made some modifications to DigitalDrifter's answer where I find the children using the template syntax. I'm pretty sure my answer will stop working after another level of children so I'm going to say DigitalDrifter still has a better answer.

Also I'm not sure how preserve the sub menues route (localhost/Traveller) so it isn't searching the children of (locathost/Traveller/View) when I click on something like view. Right now I'm doing it in kind of a janky way:

v-for="(route, index) in $router.options.routes.filter(x=>x.path==$route.path||$route.path.includes(x.path))"

Thet full SFC without styling is here:

<template>
  <nav id="sidebar">
    <div class="sidebar-header">
      <h3>Bootstrap Sidebar</h3>
    </div>

    <ul class="list-unstyled components" v-for="(route, index) in $router.options.routes.filter(x=>x.path==$route.path||$route.path.includes(x.path))">
      <li v-for="child in route.children">
        <a class="nav-item" :key="index">
          <router-link :to="{path: route.path+'/'+child.path}" exact-active-class="active">
            <icon :icon="route.icon" class="mr-2" /><span>{{ child.path }}</span>
          </router-link>
        </a>
      </li>
    </ul>

  </nav>

</template>

<script>
  export default {
    data() {
      return {
      }
    },
    methods: {
    }
  }
</script>

Edit: I know vue has the data I want associated with the routers views as shown here,

I'm just not sure how to access those properties.

Update 1/29/2019:

I figured out that all you need to do to get the path is by using $Route.matched[0].path you can learn more here.

Now I have been able to simplify the menu into an SFC like this:

<template>
    <nav id="sidebar">
      <div class="sidebar-header">
        <h3>Bootstrap Sidebar</h3>
      </div>

      <ul class="list-unstyled components" v-for="(route, index) in $router.options.routes.filter(x=>x.path==$route.matched[0].path)">
        <li v-for="child in route.children">
          <a class="nav-item"  :key="index">
            <router-link :to="route.path+'/'+child.path" exact-active-class="active">
              <icon :icon="route.icon" class="mr-2" /><span>{{ child.name }}</span>
            </router-link>
          </a>
        </li>
      </ul>

    </nav>

</template>

<script>
    export default {
    data() {
        return {
        }
      }
    }
</script>

CSS not included.

Edit: I now made this my preferred answer because it allows me to use the side menu anywhere by just referencing the component. I don't need to pass anything into it and it should work anywhere. I do like digitaldrifter's answer though because he has a fiddle for it.

这篇关于如何使用vue.js和vue路由器实现当前路由子节点的子菜单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆