Vue:如何在鼠标悬停期间以高性能方式判断是否按下了控制键?

Ada*_*ner 5 javascript vue.js

这是我第一次尝试跟踪ctrl鼠标悬停在 上时是否按下了控制键 ( ) <section>

<template>
  <section v-on:mouseover="controlKeyPressed = $event.ctrl">...</section>
</template>
Run Code Online (Sandbox Code Playgroud)

这似乎对性能非常不利,因为每次用户移动鼠标时,都需要触发此代码。理想情况下,只有在按下/释放 ctrl 键时才会运行代码。

acd*_*ior 3

这似乎对性能非常不利,因为每次用户移动鼠标时,都需要触发此代码。

在输入mouseover详细信息之前,即使该事件经常运行,也不应该对性能造成如此大的影响。由于多种原因(以及库/插件/扩展/跟踪器),这样的代码在浏览器中每秒都会运行一次。除非您不对处理程序进行任何密集的计算,否则应该没有问题。

但归根结底,在你掌握数字之前,你不应该担心这种事情。

理想情况下,只有在按下/释放 ctrl 键时才会运行代码。

mouseentermouseleave事件。但这似乎不是您要寻找的。看看他们的行为方式:

new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!',
  },
  methods: {
    imIn() {
      console.log('Mouse enters with CTRL')
    },
    imOut() {
      console.log('Mouse leaves with CTRL')
    }
  }
})
Run Code Online (Sandbox Code Playgroud)
section { background: blue; height: 30px; width: 100px; }
Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/vue@2.5.13/dist/vue.min.js"></script>

<div id="app">
  <section @mouseenter.ctrl="imIn" @mouseleave.ctrl="imOut"></section>
</div>
Run Code Online (Sandbox Code Playgroud)

事实上,mouseover 并不是每次都运行

MDN 说:

mouseover当指针设备移动到附加了侦听器的元素或其子元素之一时,会触发该事件。

所以并不是每次都运行。仅当鼠标:

  • 移动到元素上;或者
  • 移动到元素的子元素上

看看下面的方框。

new Vue({
  el: '#app',
  methods: {
    mouseOverElementWithChildren() {
      console.log('Mouse Over Element with Children', new Date())
    },
    mouseOverElementWithoutChildren() {
      console.log('Mouse Over Element WITHOUT Children', new Date())
    }
  }
})
Run Code Online (Sandbox Code Playgroud)
.nonempty { border: 1px solid red; }
.nonempty * { border: 1px solid blue; width: 200px; }

.empty { border: 1px solid green; height: 40px; }
* { font-size: small; font-family: verdana }
Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/vue@2.5.13/dist/vue.min.js"></script>

<div id="app">
  Hold CTRL and move the mouse over the elements below.<br><br>
  
  This one has many children. Notice the MOUSEOVER only triggers when you move over a line (that is, enters/leaves the element or one of its children).
  <section @mouseover.ctrl="mouseOverElementWithChildren" class="nonempty">
    <ul>
      <li>a a a</li>
      <li>b b b</li>
    </ul>
  </section>

  <br> This one has no children. Notice the MOUSEOVER only triggers when you ENTER/LEAVE the element.
  <section @mouseover.ctrl="mouseOverElementWithoutChildren" class="empty"></section>
  <br><br><br><br><br><br><br>
</div>
Run Code Online (Sandbox Code Playgroud)

针对具有多个子元素的元素的解决方法

因此,如果您不希望mouseover每次都运行代码,请创建一个空元素(这可能不是您想要的),或者在该元素之上创建一个覆盖层并将鼠标悬停事件挂接到该覆盖层。

这需要一些 CSS 工作,但是可行的:

new Vue({
  el: '#app',
  methods: {
    mouseOverElementWithChildren() {
      console.log('Mouse Over BLUE', new Date())
    },
    mouseOverElementWithoutChildren() {
      console.log('Mouse Over GREEN', new Date())
    }
  }
})
Run Code Online (Sandbox Code Playgroud)
.nonempty { border: 1px solid red; height: 70% }
.nonempty * { border: 1px solid blue; }
.empty { border: 1px solid green; width: 80%; height: 80%; }
/* below is from https://stackoverflow.com/a/2941203/1850609 */
#app { width: 100px; height: 100px; position: relative; border: 1px solid orange; }
.nonempty, .empty { position: absolute; top: 0; left: 0; }
.empty { z-index: 10; }
* { font-size: x-small; font-family: verdana }
Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/vue@2.5.13/dist/vue.min.js"></script>

Hold CTRL and move the mouse over the elements below.<br>Whole #app is orange border. Green is on top of the blue. Notice the blue does not trigger mouseOver events, and green only triggers once.
<div id="app">
  
  
  <section @mouseover.ctrl="mouseOverElementWithChildren" class="nonempty">
    <ul>
      <li>a a a</li>
      <li>b b b</li>
    </ul>
  </section>

  <section @mouseover.ctrl="mouseOverElementWithoutChildren" class="empty"></section>
  <br><br><br><br><br><br><br>
</div>
Run Code Online (Sandbox Code Playgroud)