Skip to content

事件重复绑定与stopImmediatePropagation:2018-4-17 #8

@jsonz1993

Description

@jsonz1993

本文为博客迁移过来,原文链接: 事件重复绑定与stopImmediatePropagation:2018-4-17

在旧项目中,我们一般绑定事件都是用 $('selector').on('event', fn) || document.querySelector('selector').addEventListener('event', fn);

如果平时代码规范,这样写完全ojbk 点击.p 之后输出 test1

	<div id="id">
		<p class="p">test1</p>
	</div>
	<script>
		function add(selector, fn) {
			document.querySelector(selector).addEventListener('click',fn);
		}
		add('.p', e=> console.log(e.currentTarget.innerHTML));
	</script>

但是平时如果项目不规范,代码又写的比较乱....emmmm,很有可能出现一些逻辑上的低级错误,比如这种,在某个函数调了两次,所以这里就绑定了两次...点击之后会输出两次的 test

	<div id="id">
		<p class="p">test1</p>
	</div>
	<div class="p1">test2</div>
	<script>
		function add(selector, fn) { document.querySelector(selector).addEventListener('click',fn); }
		function fn1() { add('.p', e=> console.log(e.currentTarget.innerHTML)); };
		fn1();
		fn1();
	</script>

这种情况平时工作不注意真的有可能发生,而且排查也只能说平时在看接口或改代码的时候 发现随手改
重复调接口情况

一般为了避免这种失误重复调用的操作,有几种方法:

  1. 把事件处理函数抽出来,这样就算重复绑定,浏览器检测到是同个函数引用,会做相应的优化,所以不会重复绑定到事件上
	<script>
		function add(selector, fn) { document.querySelector(selector).addEventListener('click',fn); }
		const evFn= e=> console.log(e.currentTarget.innerHTML);
		function fn1() { add('.p',  evFn)};
		fn1();
		fn1();
		fn1();
	</script>
  1. 使用 event.stopImmediatePropagation
    官方给出的说明是:
    如果某个元素有多个相同类型事件的事件监听函数,则当该类型的事件触发时,多个事件监听函数将按照顺序依次执行.如果某个监听函数执行了 event.stopImmediatePropagation()方法,则除了该事件的冒泡行为被阻止之外(event.stopPropagation方法的作用),该元素绑定的后序相同类型事件的监听函数的执行也将被阻止.

简单来说就是,执行了event.stopImmediatePropagation() 之后,后续的绑定在该dom上的相同类型事件都不再被响应,也不冒泡。

demo3 代码,点击 test1 之后,只会在控制台输出一行 test1,其他 该元素的点击事件,#id点击事件都不会被响应

	<div id="id">
		<p class="p">test1</p>
	</div>
	<script>
		function add(selector, fn) { document.querySelector(selector).addEventListener('click',fn); }
		function fn1() { add('.p',  e=> console.log(e.currentTarget.innerHTML)|| e.stopImmediatePropagation())};
		add('#id',e=>console.log(1));
		fn1();
		fn1();
		fn1();
	</script>

在实际项目中,还是比较建议把事件处理逻辑抽出来当一个函数,毕竟在多人项目里面 stopImmediatePropagation 比较容易误伤队友...

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions