ChatGPT解决这个技术问题 Extra ChatGPT

Mouseover or hover vue.js

I would like to show a div when hovering over an element in vue.js. But I can't seem to get it working.

It looks like there is no event for hover or mouseover in vue.js. Is this really true?

Would it be possible to combine jquery hover and vue methods?

v-on directive works for "hover" event also. If you add to your question the code you've written we can probably help you get it working. And yes, Vue is simple and small and intended to be integrated with other packages like jQuery.

s
shakee93

i feel above logics for hover is incorrect. it just inverse when mouse hovers. i have used below code. it seems to work perfectly alright.

<div @mouseover="upHere = true" @mouseleave="upHere = false" >
    <h2> Something Something </h2>
    <some-component v-show="upHere"></some-component>
</div>

on vue instance

data : {
    upHere : false
}

Hope that helps


This should be the accepted answer! The accepted and the most upvoted answer do result in a flickering component. Every movement of the cursor on the @mouseover-div inverts the current state...
If you're showing a hidden div like a speech bubble, you'll get flickering on mouseover. Just add the same awesome mouseover/mouseleave code to the hidden div as well.
Works for me, with webpack just have to change your data as : data: () => ({ upHere: false })
For anyone struggling from flickering when child is hovered use mouseenter event instead of mouseover
D
Duka

Here is a working example of what I think you are asking for.

http://jsfiddle.net/1cekfnqw/3017/

 <div id="demo">
        <div v-show="active">Show</div>
        <div @mouseover="mouseOver">Hover over me!</div>
    </div>

var demo = new Vue({
    el: '#demo',
    data: {
        active: false
    },
    methods: {
        mouseOver: function(){
            this.active = !this.active;   
        }
    }
});

does not work with newest vue version. @CYB tried to edit your answer to v-on:mouseover="mouseOver" but did not mention in which version of vue the syntax changed
@NICO has a better solution than mine and works with the current version (1.0.26 at the time of this post). Please reference his answer. Thank you.
I would like to delete this since I just stated, the post below by @NICO is better than mine, and more up to date. Please Give NICO that correct answer, and I will delete mine. Thank you!
the example is broken?
i think better use short hand @mouseover:mouseover
N
NICO

There's no need for a method here.

HTML

<div v-if="active">
    <h2>Hello World!</h2>
 </div>

 <div v-on:mouseover="active = !active">
    <h1>Hover me!</h1>
 </div>

JS

new Vue({
  el: 'body',
  data: {
    active: false
  }
})

You can use either v-on:mouseover or the shortcut @mouseover per the docs vuejs.org/guide/syntax.html#v-on-Shorthand
You can replace on with v-on: or @ for any of the html event attributes. w3schools.com/tags/ref_eventattributes.asp
What's the problem? This one is working and should be marked as the correct answer.
Vue 2.2.0 don't like this - spit a warning "[Vue warn]: Do not mount Vue to or - mount to normal elements instead. "
For the sake of simplicity i made a vue instance. Of course you shouldnt do that in your real world application.
q
qsc vgy

To show child or sibling elements it's possible with CSS only. If you use :hover before combinators (+, ~, >, space). Then the style applies not to hovered element.

HTML

<body>
  <div class="trigger">
    Hover here.
  </div>
  <div class="hidden">
    This message shows up.
  </div>
</body>

CSS

.hidden { display: none; }
.trigger:hover + .hidden { display: inline; }

The questioner is specifically asking about vue.js. Since it allows javascript to be easily bound to the mouseover event.
I'm using Vue and this is the best solution for me. I have a nested list with buttons that should only appear on hover, and using extra variables to track the hover state is overkill. CSS is much more elegant. Thanks qsc!
u
user2976753

With mouseover and mouseleave events you can define a toggle function that implements this logic and react on the value in the rendering.

Check this example:

var vm = new Vue({ el: '#app', data: {btn: 'primary'} });


css postprocessors e.g. purgecss will not be able to pick up your classes if you dynamically build them like this. better: @mouseover="btn-color='btn-warning' @mouseleave="btn-color='btn-primary' :class="btn btn-block { btn-color}"
C
Community

Though I would give an update using the new composition api.

Component

<template>
  <div @mouseenter="hovering = true" @mouseleave="hovering = false">
    {{ hovering }}
  </div>
</template>

<script>
  import { ref } from '@vue/composition-api'

  export default {
    setup() {
      const hovering = ref(false)
      return { hovering }
    }
  })
</script>

Reusable Composition Function

Creating a useHover function will allow you to reuse in any components.

export function useHover(target: Ref<HTMLElement | null>) {
  const hovering = ref(false)

  const enterHandler = () => (hovering.value = true)
  const leaveHandler = () => (hovering.value = false)

  onMounted(() => {
    if (!target.value) return
    target.value.addEventListener('mouseenter', enterHandler)
    target.value.addEventListener('mouseleave', leaveHandler)
  })

  onUnmounted(() => {
    if (!target.value) return
    target.value.removeEventListener('mouseenter', enterHandler)
    target.value.removeEventListener('mouseleave', leaveHandler)
  })

  return hovering
}

Here's a quick example calling the function inside a Vue component.

<template>
  <div ref="hoverRef">
    {{ hovering }}
  </div>
</template>

<script lang="ts">
  import { ref } from '@vue/composition-api'
  import { useHover } from './useHover'

  export default {
    setup() {
      const hoverRef = ref(null)
      const hovering = useHover(hoverRef)
      return { hovering, hoverRef }
    }
  })
</script>

You can also use a library such as @vuehooks/core which comes with many useful functions including useHover.

Reference: Vuejs composition API


P
Penny Liu

I think what you want to achieve is with the combination of

@mouseover, @mouseout, @mouseenter and @mouseleave

So the two best combinations are

"@mouseover and @mouseout"

or

"@mouseenter and @mouseleave"

And I think, It's better to use the 2nd pair so that you can achieve the hover effect and call functionalities on that.

    <div @mouseenter="activeHover = true" @mouseleave="activeHover = false" >
        <p v-if="activeHover"> This will be showed on hover </p>
        <p v-if ="!activeHover"> This will be showed in simple cases </p>
    </div>    

on vue instance

    data : {
        activeHover : false
    }

Note: 1st pair will effect/travel on the child elements as well but 2nd pair will only effect where you want to use it not the child elements. Else you will experience some glitch/fluctuation by using 1st pair. So, better to use 2nd pair to avoid any fluctuations.

I hope, it will help others as well :)


B
Brian Lee

It's possible to toggle a class on hover strictly within a component's template, however, it's not a practical solution for obvious reasons. For prototyping on the other hand, I find it useful to not have to define data properties or event handlers within the script.

Here's an example of how you can experiment with icon colors using Vuetify.

new Vue({ el: '#app' })

delete launch check


b
besthost

With mouseover only the element stays visible when mouse leaves the hovered element, so I added this:

@mouseover="active = !active" @mouseout="active = !active"

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

L
LittleStupid

I came up with the same problem, and I work it out !


f
funkvn

There is a correct working JSFiddle: http://jsfiddle.net/1cekfnqw/176/

<p v-on:mouseover="mouseOver" v-bind:class="{on: active, 'off': !active}">Hover over me!</p>

N
N. Kudryavtsev

Please take a look at the vue-mouseover package if you are not satisfied with how does this code look:

<div
    @mouseover="isMouseover = true"
    @mouseleave="isMouseover = false"
/>

vue-mouseover provides a v-mouseover directive that automaticaly updates the specified data context property when the cursor enters or leaves an HTML element the directive is attached to.

By default in the next example isMouseover property will be true when the cursor is over an HTML element and false otherwise:

<div v-mouseover="isMouseover" />

Also by default isMouseover will be initially assigned when v-mouseover is attached to the div element, so it will not remain unassigned before the first mouseenter/mouseleave event.

You can specify custom values via v-mouseover-value directive:

<div
    v-mouseover="isMouseover"
    v-mouseover-value="customMouseenterValue"/>

or

<div
    v-mouseover="isMouseover"
    v-mouseover-value="{
        mouseenter: customMouseenterValue,
        mouseleave: customMouseleaveValue
    }"
/>

Custom default values can be passed to the package via options object during setup.


H
Hardik Raval

Here is a very simple example for MouseOver and MouseOut:

<div id="app">
   <div :style = "styleobj" @mouseover = "changebgcolor" @mouseout = "originalcolor"> 
   </div>
</div>

new Vue({
  el:"#app",
  data:{
     styleobj : {
       width:"100px",
       height:"100px",
       backgroundColor:"red"
     }
  },
  methods:{
    changebgcolor : function() {
      this.styleobj.backgroundColor = "green";
    },
    originalcolor : function() {
      this.styleobj.backgroundColor = "red";
    }
  }
});

a
atazmin

This worked for me for nuxt

<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>