简体   繁体   中英

Dropdown menu in VueJS (toggling of active menu)

This is the menu and below my navigation menu and method that on click should open the subitems inside nav item on click but I cant seem to be find where I'm lacking

[![dropdown_menu][1]][1]

 new Vue({ el: '#app', data: { //menu "menu_title": "a", "child_routes": [{ "path": "/a1", "menu_title": "a1" }, { "path": "/a2", "menu_title": "a2" } ] }, { "menu_title": "b", "child_routes": [{ "path": "/b1", "menu_title": "b1" }, { "path": "/b2", "menu_title": "b2" }, { "path": "/b1", "menu_title": "b3" } ] }, { "menu_title": "c", "child_routes": [{ "path": "/c1", "menu_title": "c1" }, { "path": "/c2", "menu_title": "c2" }, { "path": "/c3", "menu_title": "c3" } ] } }, methods: { navlinks() { var navItemParent = document.querySelector("nav-item"); var navLink = document.querySelector(".idb-nav .nav-item .nav-link"); var navItem = document.querySelector(".idb-nav .nav-item"); navItem.classList.toggle("active"); if (navItem.contains("active")) { navItem.classList.remove("active"); navLink.classList.toggle("active"); } } ) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <nav class="idb-sidebar-nav"> <ul class="idb-nav list-unstyled m-15 p-0"> <template v-for="(menu, index) in sideBarLinks.routes"> <li class="nav-item" v-if="menu.child_routes!=null" :key="index"> <a href="javascript:void(0)" class="nav-link" @click="navlinks" > <i :class="menu.menu_icon" class="menu-icon"></i> <span class="menu-title">{{menu.menu_title}}</span> </a> <ul class="list-unstyled sub-menu"> <router-link :to="subMenu.path" tag="li" v-for="(subMenu, key) in menu.child_routes" :key="key" > <a href="javascript:void(0)" class="sub-menu-nav-link"> <span>{{subMenu.menu_title}}</span> </a> </router-link> </ul> </li> <router-link :key="index" :to="menu.path" tag="li" class="nav-item" v-else > <a class="nav-link"> <i :class="menu.menu_icon" class="mr-15"></i> <span class="menu-title">{{menu.menu_title }}</span> </a> </router-link> </template> </ul> </nav> </div> 

The classes toggling should be managed as part of the data . Try this and see if it works for you:

HTML

<div id="app">
   <nav class="idb-sidebar-nav">
      <ul class="idb-nav list-unstyled m-15 p-0">
         <template v-for="(menu, index) in sideBarLinks.routes" :key="index">
            <li class="nav-item"
                  v-if="menu.child_routes && menu.child_routes.length">

               <a :class="[ 'nav-link', { 'active': menu.active } ]"
                  href="javascript:void(0);"
                  @click="toggleMenu(index)">

                  <i :class="menu.menu_icon" class="menu-icon"></i>
                  <span class="menu-title">{{menu.menu_title}}</span>
               </a>

               <ul class="list-unstyled sub-menu">
                  <router-link tag="li"
                               v-for="(subMenu, key) in menu.child_routes"
                               :key="key"
                               :to="subMenu.path">
                     <a href="javascript:void(0);" class="sub-menu-nav-link">
                        <span>{{subMenu.menu_title}}</span>
                     </a>
                  </router-link>
               </ul>
            </li>

            <router-link v-else
                         :key="index"
                         :to="menu.path"
                         tag="li"
                         class="nav-item">

               <a :class="[ 'nav-link', { 'active': menu.active } ]"
                  href="javascript:void(0);"
                  @click="toggleMenu(index)">

                  <i :class="menu.menu_icon" class="mr-15"></i>
                  <span class="menu-title">{{menu.menu_title }}</span>
               </a>

            </router-link>
         </template>
      </ul>
   </nav>
</div>

routes.json

For improved readability and maintainability, you'd best be moving the list to separate file.

[
   {
      "menu_title": "a",
      "child_routes": [
         {
            "path": "/a1",
            "menu_title": "a1"
         },
         {
            "path": "/a2",
            "menu_title": "a2"
         }
      ],
      active: true // First item opened by default (if you like)
   },
   {
      "menu_title": "b",
      "child_routes": [
         {
            "path": "/b1",
            "menu_title": "b1"
         },
         {
            "path": "/b2",
            "menu_title": "b2"
         },
         {
            "path": "/b1",
            "menu_title": "b3"
         }
      ],
      active: false
   },
   {
      // ...
   }
]

app.js

import * as routes from './routes.json';

const vm = new Vue({
   el: '#app',

   data() {
      return {
         sideBarLinks: {
            routes
         }
      }
   },

   methods: {
      toggleSidebar(index) {
         this.sideBarLinks
            .routes
            .forEach((menu, i) => menu.active = (i === index));
      }
   }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM