【问题标题】:Event-bubbling of a draw() function in JSJS 中 draw() 函数的事件冒泡
【发布时间】:2016-05-16 13:37:20
【问题描述】:

如下代码sn-p展示核心结构:

EDIT1:

var smthing = 0;
change_name_button.addEventListener('click', function(event){
    // some query
    // .....

    // result from query
    data = res.name.coords;

    // tried to make the function go to GC
    smthing = null;
    delete smthing;
    smthing = new drawMouseMovement(data);

    event.stopPropagation();
}, false);      

function drawMouseMovement(data){
    // bunch of variables set for drawing function
    // .....
    // .....
    var test = 0;

    // draw something to canvas until end "maxLength" is reached
    var draw = function() {
        if(t < maxLength){
            // redraw some stuff to canvas
            // .....
        }else{
            return;
        }
    }

    // function to play pause and replay the drawing on canvas
    function playPause(boolPP, boolRP){
        if(boolPP){
            test = setInterval(draw, 10);
        }else{
            clearInterval(test);
        }
        if(boolRP){
            // some params being reset
            // .....

            test = setInterval(draw, 10);
        }
    }

    function play(event){
        playPause(true, false);
        event.stopPropagation();
    }

    function pause(event){
        playPause(false, false);
        event.stopPropagation();
    }

    function replay(event){
        playPause(false, true);
        event.stopPropagation();
    }

    play_button.addEventListener('click', play, false);

    pause_button.addEventListener('click', pause, false);

    replay_button.addEventListener('click', replay, false);
}

每次点击change_name_buttondrawMouseMovement() 都会使用新参数调用。

如下问题:当再次点击change_name_button之前绘制函数没有到达return时,同一函数有两个实例同时绘制两个不同的东西。只有函数的最后一个调用实例应该是绘图。

我尝试删除指向函数clearInterval()removeEventListener 的指针。但我似乎没有让任何这些工作。

我希望我的问题很清楚。 提前致谢。

编辑

问题的简单复制。 some_button 是否单击一次,smt 每 250 毫秒打印一次。是否第二次单击 some_button,每 125 毫秒打印一次 smt 等。如何在下次单击时覆盖 printer() 的第一个实例?

some_button.addEventListener('click', foo, false);

function foo(event) {
    printer();
    event.stopPropagation();
}

function printer(){
    setInterval(function() {
        console.log("smt");
    }, 250);
}

【问题讨论】:

  • 这一行看起来好像您正在创建一个新函数对象而不是结束旧函数对象:smthing = new drawMouseMovement(data); 我有一个更新演示了一个事件监听器,多个event.targets
  • 当归结为几百毫秒之间的差异时,几乎不可能在很小的时间窗口内进行如此精确的控制。一般来说,JavaScript 总是平均关闭 5 到 10 毫秒。你看过那个演示吗?我使用了一个开关来路由功能,以便您能够触发一个事件。你现在拥有它的方式是: 1 单击 4 eventListener 4 个函数。我的演示:1 click 1 eventlistener 4 functions。如果你的绘图函数有一个延长的持续时间,那么你应该尝试创建一个类或一个函数装饰器。这些是高级模式。继续-->
  • 查看有关打印功能的更新。

标签: javascript draw event-bubbling


【解决方案1】:

更新 2

问题的简单复制。是否单击了某个按钮,每 250 毫秒打印一次 smt。是否第二次单击了 some_button,每 125 毫秒打印一次 smt 等。如何在下次单击时覆盖打印机()的第一个实例?

不可能!不要杀死函数,让它运行。首先,您需要一个计数器来计算点击次数,以便函数知道它已被第二次点击。其次,只需为第二次单击按钮时添加额外的行为,在这种情况下,您将获得一半的时间间隔。

好的,当我说 JavaScript 时间很古怪时,我的意思是 fu#@3d。 setInterval 需要 clearInterval 来阻止它。大多数文章和教程没有说的是该死的setInterval 仍然存在,因此将其设为null 将允许您创建一个新的。我决定制作一个构造函数计时器。

  • 演示中有一个按钮,点击它,它会每 2 秒打印一次 'smt' 加上开始新间隔的点击次数。

  • “Go”按钮被“Stop”按钮取代,一旦点击它就会像宣传的那样——停止

  • 再次单击它,它是“开始”按钮,但这一次,它现在每秒打印一次。

  • 起泡、冲洗、重复。

用一些原型魔法重构这个演示,你就得到了一个类。

PLUNKER - TIMER CONSTRUCTOR

PLUNKER - 1 EVENTLISTENER, MULTIPLE EVENT.TARGETS

片段

<!DOCTYPE html>
<html>
<head>
<style>
.on { display: block; }
button { display: none; }
</style>
</head>
<body>

<button id="btn1" class="on">Go</button><button id="btn2" class="">Stop</button>
<script>
var btn1 = document.getElementById('btn1');
var btn2 = document.getElementById('btn2');
var counter = 0;
var timer = new Timer();
btn1.addEventListener('click', xStart, false);
btn2.addEventListener('click', xStop, false);

function xStart(event) { 
  timer.term;
  counter++;
  timer.start(counter);
	btn1.classList.toggle('on');
	btn2.classList.toggle('on');

	event.stopPropagation(); 
}

function xStop(event) {
	timer.term();
	btn1.classList.toggle('on');
	btn2.classList.toggle('on');
	event.stopPropagation(); 
}

function Timer(c){
  var self = this;

  self.start = function(c){
		var t = self.printer(c);
    self.interval = setInterval(function() { self.printer(c); },t);
  };
  
	self.term = function(){
		self.clear = clearInterval(self.interval);
		self.null;
	};
	
  self.printer = function(x){
    var d = (x % 2 === 0) ? 2 : 1;
	  var t = 2000 / d;
	  console.log('smt'+x+' t: '+t);
	  return t;
  };
}

</script>

</body>
</html>

更新 1

以下 Plunker 演示了如何使唯一的 eventListener 成为按钮作为父级共享的元素。

PLUNKER


您的eventListeners() 都没有任何用于捕获阶段的内容,尽管我认为默认情况下它是错误的,但无论如何都尝试将其设置为 false。

change_name_button.addEventListener('click', function(event){


    // some query
    // .....

    // result from query
    data = res.name.coords;

    // tried to make the function go to GC
    smthing = null;
    delete smthing;
    smthing = new drawMouseMovement(data);

    event.stopPropagation();
}, false);  

^^^^^^^^======有捕获阶段`

在其他事件处理程序上也使用event.stopPropagation();,并将其放置在处理程序末尾附近。不要忘记传递(event) 对象。

   function play(event){
        playPause(true, false);
        event.stopPropagation();
    }

    function pause(event){
        playPause(false, false);
        event.stopPropagation();
    }

    function replay(event){
        playPause(false, true);
        event.stopPropagation();
    }

 play_button.addEventListener('click', play, false);

 pause_button.addEventListener('click', pause, false);

 replay_button.addEventListener('click', replay, false);

另外,如果这不能解决问题,那么您需要发布 HTML,因为您的 event.targetevent.currentTarget 的布局可能需要调整。

编辑

尝试更改if else

function drawMouseMovement(data){
    // bunch of variables set for drawing function
    // .....
    // .....
    var test = 0;

    // draw something to canvas until end "maxLength" is reached
    var draw = function() {
        if(t < maxLength){
            // redraw some stuff to canvas
            // .....
        }
        // when t has reached maxlength, then it should quit?
        return false;
    }

【讨论】:

  • 遗憾的是,您的第一个建议没有奏效。我还是更新了它并包含了 html sn-p。你能澄清一下你最后一句话的意思吗?
  • 如果您将 eventListener 分组在一个公共父元素下,则有一种方法可以隔离每个单击的元素,从而防止在冒泡阶段发生不必要的调用。
  • 我注意到 drawMouseMovement(data) 的 if else 部分可能会有所不同,但我不能 100% 确定,因为它不完整。我会用建议更新答案,待命....
  • 澄清一下,只有在再次调用drawMouseMovement() 之前t 没有到达maxLength 时才会出现问题。所以return必须在下一个实例启动之前为函数的实例触发。
  • 我想到了绘图功能,这就是为什么我建议你放弃else return false 并改用return false。如果有 !t t = undefined ,看起来你有 elseif(t &lt; maxlength)... 声明里面是个谜,所以我不知道你在 t&lt;maxlength 时有什么退出计划。但是,该特定声明是写的,我相信这是瓶颈。 smthing = new drawMouseMovement(data); 也是可疑的......
猜你喜欢
  • 2021-08-14
  • 1970-01-01
  • 2015-08-12
  • 2011-10-20
  • 2011-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多