Vue.js 在Bulma中导航到其他链接时,如何关闭可悬停下拉列表?

Vue.js 在Bulma中导航到其他链接时,如何关闭可悬停下拉列表?,vue.js,hover,dropdown,nuxt.js,bulma,Vue.js,Hover,Dropdown,Nuxt.js,Bulma,我在导航栏里有一个可悬停的下拉菜单 当我移动到另一个页面时,下拉列表仍然打开 我在普莱恩布尔马试过,问题仍然存在 我正在使用SSR访问Nuxt.js 我正在使用nuxt link/相当于Vue路由器链接的链接导航到其他页面 这是我的默认.vue文件 <template> <div class="ch-container"> <header class="ch-header"> <nav

  • 我在导航栏里有一个可悬停的下拉菜单
  • 当我移动到另一个页面时,下拉列表仍然打开
  • 我在普莱恩布尔马试过,问题仍然存在
  • 我正在使用SSR访问Nuxt.js
  • 我正在使用nuxt link/相当于Vue路由器链接的链接导航到其他页面
这是我的默认.vue文件

<template>
  <div class="ch-container">
    <header class="ch-header">
      <nav
        class="navbar is-fixed-top"
        role="navigation"
        aria-label="main navigation"
      >
        <div class="navbar-brand">
          <nuxt-link class="navbar-item" to="/">
            <img
              alt="CH Logo"
              src="https://i.imgur.com/v35Kfc9.png"
              width="28"
              height="28"
            />
          </nuxt-link>

          <a
            role="button"
            class="navbar-burger burger"
            aria-label="menu"
            aria-expanded="false"
            data-target="navbarBasicExample"
          >
            <span aria-hidden="true"></span>
            <span aria-hidden="true"></span>
            <span aria-hidden="true"></span>
          </a>
        </div>

        <div id="navbarBasicExample" class="navbar-menu">
          <div class="navbar-start">
            <nuxt-link class="navbar-item" to="/news">
              News
            </nuxt-link>

            <nuxt-link class="navbar-item" to="/resources">
              Resources
            </nuxt-link>

            <nuxt-link class="navbar-item" to="/tickers">
              Tickers
            </nuxt-link>

            <div class="navbar-item has-dropdown is-hoverable">
              <a class="navbar-link">
                More
              </a>
              <div class="navbar-dropdown">
                <a class="navbar-item">
                  FAQ
                </a>
                <nuxt-link class="navbar-item" to="/contact">
                  Contact
                </nuxt-link>
                <hr class="navbar-divider" />
                <a class="navbar-item">
                  Feature Request
                </a>
              </div>
            </div>
          </div>

          <div class="navbar-end">
            <div class="navbar-item">
              <a href="#">
                <fa :icon="faMoon" />
              </a>
            </div>
            <div class="navbar-item has-dropdown is-hoverable">
              <a class="navbar-link is-arrowless">
                <fa :icon="faExclamationCircle" />
              </a>
              <div class="navbar-dropdown">
                <a class="navbar-item">
                  No new notifications
                </a>
              </div>
            </div>
            <div class="navbar-item">
              <div class="buttons">
                <nuxt-link class="button is-primary" to="/signup">
                  <strong>Sign up</strong>
                </nuxt-link>
                <nuxt-link id="login" class="button is-light" to="/login">
                  Log in
                </nuxt-link>
              </div>
            </div>
          </div>
        </div>
      </nav>
    </header>
    <main class="ch-main">
      <nuxt />
    </main>
    <footer class="ch-footer is-hidden-mobile">
      <div class="level">
        <div class="level-left">
          <div class="level-item">
            <a href="#">
              <span class="icon">
                <fa :icon="faFacebookSquare" />
              </span>
            </a>
            <a href="#">
              <span class="icon">
                <fa :icon="faTwitterSquare" />
              </span>
            </a>
            <a href="#">
              <span class="icon">
                <fa :icon="faRedditSquare" />
              </span>
            </a>
          </div>
        </div>
        <div class="level-right">
          <div class="level-item">
            &copy;ch, All Rights Reserved
          </div>
          <div class="level-item">
            <nuxt-link to="/contact">Contact</nuxt-link>
          </div>
          <div class="level-item">
            <nuxt-link to="/terms-of-service">Terms</nuxt-link>
          </div>
          <div class="level-item">
            <nuxt-link to="/privacy-policy">Privacy</nuxt-link>
          </div>
        </div>
      </div>
    </footer>
  </div>
</template>

<script>
import {
  faFacebookSquare,
  faTwitterSquare,
  faRedditSquare,
} from '@fortawesome/free-brands-svg-icons'

import { faMoon, faExclamationCircle } from '@fortawesome/free-solid-svg-icons'

export default {
  computed: {
    faFacebookSquare() {
      return faFacebookSquare
    },
    faTwitterSquare() {
      return faTwitterSquare
    },
    faRedditSquare() {
      return faRedditSquare
    },
    faMoon() {
      return faMoon
    },
    faExclamationCircle() {
      return faExclamationCircle
    },
  },

  mounted() {
    // Get all "navbar-burger" elements
    const $navbarBurgers = Array.prototype.slice.call(
      document.querySelectorAll('.navbar-burger'),
      0
    )

    // Check if there are any navbar burgers
    if ($navbarBurgers.length > 0) {
      // Add a click event on each of them
      $navbarBurgers.forEach((el) => {
        el.addEventListener('click', () => {
          // Get the target from the "data-target" attribute
          const target = el.dataset.target
          const $target = document.getElementById(target)

          // Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
          el.classList.toggle('is-active')
          $target.classList.toggle('is-active')
        })
      })
    }
  },
}
</script>

<style></style>

&抄袭;版权所有
接触
条款
隐私
进口{
faFacebookSquare,
faTwitterSquare,
faRedditSquare,
}来自“@fortwome/free brands svg icons”
从“@fortawesome/free solid svg icons”导入{faMoon,fa惊叹圈}
导出默认值{
计算:{
faFacebookSquare(){
返回faFacebookSquare
},
faTwitterSquare(){
返回faTwitterSquare
},
faRedditSquare(){
回程票价广场
},
法蒙(){
回报
},
fa惊叹圆(){
返回fa感叹词圆
},
},
安装的(){
//获取所有“navbar汉堡”元素
const$navbarBurgers=Array.prototype.slice.call(
document.queryselectoral('.navbar burger'),
0
)
//检查是否有navbar汉堡
如果($navbarBurgers.length>0){
//在每个按钮上添加单击事件
$navbarBurgers.forEach((el)=>{
el.addEventListener('单击',()=>{
//从“数据目标”属性获取目标
const target=el.dataset.target
const$target=document.getElementById(目标)
//在“导航栏汉堡”和“导航栏菜单”上切换“是活动的”类
el.classList.toggle('is-active')
$target.classList.toggle('is-active')
})
})
}
},
}
这是一张GIF图片,说明了这个问题


移动到另一个页面后如何关闭下拉列表?

好的,整个过程很复杂,因为悬停是由css触发的,因此当鼠标悬停在下拉列表上时,总是可以看到下拉列表。您必须覆盖此状态并使用vue事件解决它。我们还必须在路线上设置一个观察者来重置状态



好的,整个事情使它变得复杂,因为悬停是由css触发的,因此当鼠标在它上面时,总是可以看到下拉列表。您必须覆盖此状态并使用vue事件解决它。我们还必须在路线上设置一个观察者来重置状态



这是我的工作形式引导5,在触摸设备上使用点击,在设备上使用鼠标悬停

<template>
  <span
    v-if="item"
    class="primary-navigation-list-dropdown"
    @mouseover="isTouchscreenDevice ? null : openDropdownMenu()"
    @mouseleave="isTouchscreenDevice ? null : closeDropdownMenu()"
  >
    <nuxt-link
      to="#"
      @click.prevent.native="openDropdownMenu"
      v-click-outside="closeDropdownMenu"
      :title="item.title"
      :class="[
        item.cssClasses,
        { show: isDropdownMenuVisible }
      ]"
      :id="`navbarDropdownMenuLink-${item.id}`"
      :aria-expanded="[isDropdownMenuVisible ? true : false]"
      class="
        primary-navigation-list-dropdown__toggle
        nav-link
        dropdown-toggle"
      aria-current="page"
      role="button"
      data-toggle="dropdown"
    >
      {{ item.label }}
    </nuxt-link>
    <ul
      :class="{ show: isDropdownMenuVisible }"
      :aria-labelledby="`navbarDropdownMenuLink-${item.id}`"
      class="
        primary-navigation-list-dropdown__menu
        dropdown-menu-list
        dropdown-menu"
    >
      <li
        v-for="item in item.children" :key="item.id"
        class="dropdown-menu-list__item"
      >
        <NavLink
          :attributes="item"
          class="dropdown-menu-list__link dropdown-item"
        />
      </li>
    </ul>
  </span>
</template>

<script>
import NavLink from '@/components/Navigation/NavLink';

export default {
  name: "DropdownMenu",
  props: {
    item: {
      type: Object,
      required: true,
    },
  },
  data() {
    return {
      isDropdownMenuVisible: false,
      isTouchscreenDevice: false
    };
  },
  mounted() {
    this.detectTouchscreenDevice();
  },
  methods: {
    openDropdownMenu() {
      if (this.isTouchscreenDevice) {
        this.isDropdownMenuVisible = !this.isDropdownMenuVisible;
      } else {
        this.isDropdownMenuVisible = true;
      }
    },

    closeDropdownMenu() {
      if (this.isTouchscreenDevice) {
        this.isDropdownMenuVisible = false;
      } else {
        this.isDropdownMenuVisible = false;
      }
    },

    detectTouchscreenDevice() {
      if (window.PointerEvent && ('maxTouchPoints' in navigator)) {
        if (navigator.maxTouchPoints > 0) {
          this.isTouchscreenDevice = true;
        }
      } else {
        if (window.matchMedia && window.matchMedia("(any-pointer:coarse)").matches) {
          this.isTouchscreenDevice = true;
        } else if (window.TouchEvent || ('ontouchstart' in window)) {
          this.isTouchscreenDevice = true;
        }
      }
      return this.isTouchscreenDevice;
    }
  },
  components: {
    NavLink
  }
};
</script>

<style scoped lang="scss">
.primary-navigation-list-dropdown {
  &__toggle {
    color: $white;

    &:hover {
      color: $blue;
    }
  }

  &__menu {
    margin-top: 0;
  }

  &__dropdown {

  }
}

.dropdown-menu-list {
  &__item {

  }

  &__link {
    &.active,
    &.nuxt-link-exact-active {
      border-bottom: 1px solid $blue;
    }
  }
}
</style>

这是我的工作形式引导5,在触摸设备上使用点击,在设备上使用鼠标悬停

<template>
  <span
    v-if="item"
    class="primary-navigation-list-dropdown"
    @mouseover="isTouchscreenDevice ? null : openDropdownMenu()"
    @mouseleave="isTouchscreenDevice ? null : closeDropdownMenu()"
  >
    <nuxt-link
      to="#"
      @click.prevent.native="openDropdownMenu"
      v-click-outside="closeDropdownMenu"
      :title="item.title"
      :class="[
        item.cssClasses,
        { show: isDropdownMenuVisible }
      ]"
      :id="`navbarDropdownMenuLink-${item.id}`"
      :aria-expanded="[isDropdownMenuVisible ? true : false]"
      class="
        primary-navigation-list-dropdown__toggle
        nav-link
        dropdown-toggle"
      aria-current="page"
      role="button"
      data-toggle="dropdown"
    >
      {{ item.label }}
    </nuxt-link>
    <ul
      :class="{ show: isDropdownMenuVisible }"
      :aria-labelledby="`navbarDropdownMenuLink-${item.id}`"
      class="
        primary-navigation-list-dropdown__menu
        dropdown-menu-list
        dropdown-menu"
    >
      <li
        v-for="item in item.children" :key="item.id"
        class="dropdown-menu-list__item"
      >
        <NavLink
          :attributes="item"
          class="dropdown-menu-list__link dropdown-item"
        />
      </li>
    </ul>
  </span>
</template>

<script>
import NavLink from '@/components/Navigation/NavLink';

export default {
  name: "DropdownMenu",
  props: {
    item: {
      type: Object,
      required: true,
    },
  },
  data() {
    return {
      isDropdownMenuVisible: false,
      isTouchscreenDevice: false
    };
  },
  mounted() {
    this.detectTouchscreenDevice();
  },
  methods: {
    openDropdownMenu() {
      if (this.isTouchscreenDevice) {
        this.isDropdownMenuVisible = !this.isDropdownMenuVisible;
      } else {
        this.isDropdownMenuVisible = true;
      }
    },

    closeDropdownMenu() {
      if (this.isTouchscreenDevice) {
        this.isDropdownMenuVisible = false;
      } else {
        this.isDropdownMenuVisible = false;
      }
    },

    detectTouchscreenDevice() {
      if (window.PointerEvent && ('maxTouchPoints' in navigator)) {
        if (navigator.maxTouchPoints > 0) {
          this.isTouchscreenDevice = true;
        }
      } else {
        if (window.matchMedia && window.matchMedia("(any-pointer:coarse)").matches) {
          this.isTouchscreenDevice = true;
        } else if (window.TouchEvent || ('ontouchstart' in window)) {
          this.isTouchscreenDevice = true;
        }
      }
      return this.isTouchscreenDevice;
    }
  },
  components: {
    NavLink
  }
};
</script>

<style scoped lang="scss">
.primary-navigation-list-dropdown {
  &__toggle {
    color: $white;

    &:hover {
      color: $blue;
    }
  }

  &__menu {
    margin-top: 0;
  }

  &__dropdown {

  }
}

.dropdown-menu-list {
  &__item {

  }

  &__link {
    &.active,
    &.nuxt-link-exact-active {
      border-bottom: 1px solid $blue;
    }
  }
}
</style>

有工作代码吗??回购@HardikShah也修改了这个问题,添加了一个沙盒来解决这个问题,试着从更多的下拉列表中导航到另一个页面,任何工作代码??回购@HardikShah也修改了这个问题,在问题中加入了一个沙盒,尝试从“更多”下拉列表导航到另一个页面
<template>
  <component
    :is="attributes"
    v-bind="linkAttributes(attributes.path)"
    :title="attributes.title"
    :class="[ attributes.cssClasses ]"
    class="nav-link active_"
    aria-current="page"
    prefetch
  >
  {{ attributes.label }}
  </component>
</template>

<script>
export default {
  name: 'NavLink',
  props: {
    attributes: {
      type: Object,
      required: true
    }
  },
  methods: {
    linkAttributes(path) {
      if (path.match(/^(http(s)?|ftp):\/\//) || path.target === '_blank') {
        return {
          is: 'a',
          href: path,
          target: '_blank',
          rel: 'noopener'
        }
      }
      return {
        is: 'nuxt-link',
        to: path
      }
    }
  }
}
</script>
import Vue from 'vue'

Vue.directive('click-outside', {
  bind: function (el, binding, vnode) {
    el.clickOutsideEvent = function (event) {
      if (!(el == event.target || el.contains(event.target))) {
        vnode.context[binding.expression](event);
      }
    };
    document.body.addEventListener('click', el.clickOutsideEvent)
  },
  unbind: function (el) {
    document.body.removeEventListener('click', el.clickOutsideEvent)
  },
});