【问题标题】:Does an event listener function defined inside another event listener function access the copy of global variables?在另一个事件侦听器函数中定义的事件侦听器函数是否访问全局变量的副本?
【发布时间】:2021-10-28 00:54:19
【问题描述】:

我正在尝试制作一个可以移动到任何位置的 div,例如拖放功能。我使用了以下方法:

var songs = {};
songs.clickedM = 0;
$(".song-progress .current-position")[0].addEventListener("mousedown", function(down2) {
songs.clickedM = 1;
var intpos2 = down2.clientX;

$(".song-progress .current-position")[0].addEventListener( "mousemove", function(Dmove2) {

    if(songs.clickedM == 1) {           

        if (Dmove2.clientX <= $(".song-progress").offset().left) {
            $(".song-progress .current-position")[0].style.left = "0px";
            
        }
        else if( Dmove2.clientX >= ($(".song-progress").outerWidth() + $(".song-progress").offset().left)) {
            $(".song-progress .current-position")[0].style.left = ( $(".song-progress").outerWidth() - 14) + "px";
           
        }
        else {
            $(".song-progress .current-position")[0].style.left = (Dmove2.clientX - $(".song-progress").offset().left ) + "px";
           
        }
    }

});

});

$("body")[0].addEventListener("mouseup", function() {


songs.clickedM = 0;
   
});
.container {
  padding: 100px;
  width: 700px;
  height: 500px;
  background-color: lightgray;
}
.song-progress {
        position: absolute;
        top: 84px;
        right: 15px;
        height: 5px;
        width: calc(100% - 135px);
        background-color: white;
    }
 .current-progress{
        position: absolute;
        left: 0;
        width: 0px;
        height: 5px;
        background-color: #bbb;
    }
.current-time {
        position: absolute;
        bottom: 5px;
        font-size: 10px;
        left: 0;
        font-family: "Times New Roman"
    }
 .total-time {
        position: absolute;
        bottom: 5px;
        right: 0;
        font-size: 10px;
        font-family: "Times New Roman"
    }
 .current-position {
        height: 9px;
        width: 15px;
        background-color: #00cdff;
        position: absolute;
        top: -2.5px;
        left: 1px;
        cursor: pointer;
        border-radius: 5px;
    }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
 <div class="song-progress">
                <div class="current-time">1:21</div>
                <div class="total-time">5:37</div>
                <div class="current-progress"></div>
                <div class="current-position"></div>
              </div>
              </div>

我注意到songs.clickedM 永远不会变成0,即使松开鼠标键也是如此。我的猜测是mousemove 事件监听器是一个像函数闭包一样的函数。当鼠标在第一次点击后第一次移动时,它会访问songs.clickedM 的副本而不是原始副本。它不知道原来的变量songs.clickedM实际上已经更改为0

未按下按键时如何为mousemove事件监听器设置songs.clickedM0的值?

【问题讨论】:

  • 如果您使用 Stack Snippets(&lt;&gt; 工具栏按钮)将可运行的 minimal reproducible example 添加到问题中,人们会更容易为您提供好的答案。
  • @T.J.Crowder 我添加了一个类似的版本,它仍然会重现问题。
  • 每次在.current-position 上单击鼠标时,都会添加一个新的 mousemove 侦听器。您需要在 mouseup 处理程序中删除侦听器。同样取决于页面的其他元素和 CSS,body 可能没有您想象的那么大。我宁愿将 mouseup 侦听器附加到 documentwindow
  • 首先删除alerts。 alerts 把各种事情搞砸了。 :-)
  • @user31782: alert 锁定焦点并使脚本戛然而止。使用浏览器内置的全功能调试器。这就是它的用途。关于删除处理程序:正如我在下面的答案中所说,您正在反复添加它们,因此每次按下鼠标时都会有越来越多的它们。他们都会被调用。

标签: javascript html dom dom-events mouseevent


【解决方案1】:

我的猜测是mousemove 事件监听器是一个函数,它的作用类似于函数闭包。

它不像一个闭包作用。它一个闭包。 :-)

当鼠标在第一次点击后第一次移动时,它会访问songs.clickedM 的副本而不是原始副本。它不知道原来的变量songs.clickedM实际上已经变成了0

没有。闭包可以访问它们关闭的变量,而不是它们关闭的变量的副本。即使他们收到了一份副本,在这种情况下被关闭的变量songs,它只是对一个对象的引用;它的副本仍将引用相同的对象,具有相同的 clickedM 属性。您所有的偶数处理程序都在它所引用的对象上使用 same songs 变量和相同的 clickedM 属性。问题出在其他地方。

这需要调试,但出现的一个危险信号是代码正在添加一个新的 mousemove 处理程序每次鼠标按下元素,即使它已经之前添加的。所以那些mousemove 处理程序开始堆积起来。

【讨论】:

  • 问题是别的。我不得不在 mousedown 事件中使用event.preventDefault()。因为当 div 被拖动时,文本也可以被选中。然后启动浏览器的默认拖放操作。类似于这个问题stackoverflow.com/questions/13236484/…
  • 虽然我不明白为什么我现在不必在mousemove 事件上使用event.preventDefault。拖放问题仅出现在mousemove 情况下。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-23
  • 1970-01-01
  • 2018-08-17
  • 2018-02-17
  • 2015-03-03
  • 1970-01-01
相关资源
最近更新 更多