LoginSignup
0
0

vue3.2でマルチレベルのDropdown menu

Posted at

あるようで見つからないので作りました。
スクリーンショット 2023-08-16 11.07.44.png

  • CSSはBootstrapを利用しています

template


<template>
  <nav class="navbar navbar-expand-lg navbar-light bg-light">
  <div class="container-fluid">
    <a class="navbar-brand" href="/">サイト名</a>
    <div class="collapse navbar-collapse">
      <ul class="navbar-nav me-auto mb-2 mb-lg-0">
        <li class="nav-item" v-for="level1Menu in showMenu" :key="level1Menu.name">
          <a class="nav-link " href="#" role="button" @click="level1Toggle(level1Menu)">
            {{level1Menu.name}}
          </a>
          <ul class="dropdown-menu" style="display: block;" v-show="level1Menu.show_menu">
            <li v-for="item in level1Menu.menu" :key="item.name">
              
              <router-link :to="item.to" class="dropdown-item" @click="toggle(item)">{{item.name }}</router-link>
              <ul v-show="item.showChildren">
                <li v-for="child in item.children" :key="child.name">
                  <router-link :to="child.to" class="dropdown-item" @click="toggle(child)">{{child.name }}</router-link>
                  <ul v-show="child.showChildren">
                    <li v-for="grandchild in child.children" :key="grandchild.name">
                      {{ grandchild.name }}
                    </li>
                  </ul>
                </li>
              </ul>
            </li>
          </ul>
        </li>
      </ul>
    </div>
  </div>
</nav>
</template>

script


<script setup>
import { ref } from 'vue'

const level1Toggle=(target)=>{
  const prevState = target.show_menu
  resetAll()
  //prevState : true->falseの場合は処理しない
  if(!prevState)
    target.show_menu = !target.show_menu
}

const resetAll =()=>{

  Object.keys(showMenu.value).forEach(i=>{
    
    showMenu.value[i].show_menu = false
  })
}


const menuItem1 = ref([
  { name: "子メニュー1",showChildren: false,to:"/abc",},
  { name: "子メニュー2", showChildren: false ,to:"/def",},
  { name: "子メニュー3", showChildren: false ,to:"/ghi",}
])

const menuItem2 = ref([
  { name: "子メニュー4", showChildren: false,to:"/aaaa" },
  {
    name: "子メニュー5",
    showChildren: false,
    to:"/",
    children: [
      {name: "孫メニュー1",showChildren: false,to:"/a"},
      {name: "孫メニュー2",showChildren: false,to:"/b"},
      {name: "孫メニュー3",showChildren: false,to:"/c"},
    ]
  },
  { name: "子メニュー6", showChildren: false,to:"/" },
  { name: "子メニュー7", showChildren: false,to:"/",children: [
      {name: "孫メニュー4",showChildren: false,to:"/"},
      {name: "孫メニュー5",showChildren: false,to:"/"},
    ]
   },
   { name: "子メニュー8", showChildren: false,to:"/aaaa" },

  ])


const menuItem3 = ref([

   { name: "子メニュー9", showChildren: false,to:"/b" },
   { name: "子メニュー10", showChildren: false,to:"/c" },

])

const menuItem4 = ref([
   { name: "子メニュー11", showChildren: false,to:"/d" },
])

const showMenu = ref([
  
  {name:"メニュー1",menu:menuItem1,show_menu:false},
  {name:"メニュー2",menu:menuItem2,show_menu:false},
  {name:"メニュー3",menu:menuItem3,show_menu:false},
  {name:"メニュー4",menu:menuItem4,show_menu:false},
 
])
const toggle = (item) => {
  item.showChildren = !item.showChildren
}
</script>

最後

一応コピーでも動くはずです。さらに孫メニューのデータにchildrenを増やせば曽孫メニューも出せます。

Vue.jsは使い始めて数ヶ月のため、書き方的に正しくないかもしれませんので、気になる箇所があれば、ぜひともご指摘いただければ幸いです。
現段階は「動く」を優先にしています

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0