breadCrumbs.vue 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. <template>
  2. <div class="breadcrumbs--wrap">
  3. <div class="container">
  4. <div class="menu--wrap">
  5. <p class="main--menu">{{ mainMenu }}</p>
  6. <span class="bar"></span>
  7. <div class="sub--menu--wrap" ref="menuWrap">
  8. <p class="sub--menu" @click="toggleNav" :style="{ width: width + 'px' }">
  9. <span class="ellipsis1">
  10. {{ currentSubMenu }}
  11. </span>
  12. <i class="ico"></i>
  13. </p>
  14. <div class="nav--wrap" :class="{ active: isNavOpen }">
  15. <NuxtLink
  16. v-for="(item, index) in subMenuItems"
  17. :key="index"
  18. :to="item.to"
  19. class="sub--menu2"
  20. :class="{ active: isActiveRoute(item.to) }"
  21. @click="isNavOpen = false"
  22. >
  23. {{ item.label }}
  24. </NuxtLink>
  25. </div>
  26. </div>
  27. </div>
  28. </div>
  29. </div>
  30. </template>
  31. <script setup>
  32. import { ref, onMounted, onUnmounted } from "vue";
  33. const route = useRoute();
  34. // Props 정의
  35. const props = defineProps({
  36. // 가로 넓이
  37. width: {
  38. type: String,
  39. default: "180",
  40. },
  41. // 메인 메뉴 타이틀 (예: NETWORK, VEHICLES, OWNER 등)
  42. mainMenu: {
  43. type: String,
  44. default: "NETWORK",
  45. },
  46. // 현재 선택된 서브메뉴 타이틀 (예: 전시장 및 서비스센터)
  47. currentSubMenu: {
  48. type: String,
  49. default: "메뉴를 선택하세요",
  50. },
  51. // 서브메뉴 아이템 리스트
  52. subMenuItems: {
  53. type: Array,
  54. default: () => [],
  55. // 예시 구조: [{ label: '전시장 찾기', to: '/ford/network/showroom', active: true }, ...]
  56. },
  57. });
  58. const isNavOpen = ref(false);
  59. const menuWrap = ref(null);
  60. const toggleNav = () => {
  61. isNavOpen.value = !isNavOpen.value;
  62. };
  63. // 현재 route와 비교하여 active 여부 판단
  64. const isActiveRoute = (to) => {
  65. if (!to) return false;
  66. // 현재 전체 경로 (쿼리 포함)
  67. const currentFullPath = route.fullPath;
  68. // to가 쿼리를 포함하는 경우 전체 비교
  69. if (to.includes("?")) {
  70. return currentFullPath === to || currentFullPath.startsWith(to + "&");
  71. }
  72. // 쿼리 없는 경우 path만 비교하고 쿼리가 없어야 함
  73. return route.path === to && Object.keys(route.query).length === 0;
  74. };
  75. const handleClickOutside = (event) => {
  76. if (menuWrap.value && !menuWrap.value.contains(event.target)) {
  77. isNavOpen.value = false;
  78. }
  79. };
  80. onMounted(() => {
  81. document.addEventListener("click", handleClickOutside);
  82. });
  83. onUnmounted(() => {
  84. document.removeEventListener("click", handleClickOutside);
  85. });
  86. </script>