Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
jsonz1993 opened this issue Jul 27, 2021 · 0 comments
Open

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

jsonz1993 opened this issue Jul 27, 2021 · 0 comments

Comments

@jsonz1993
Copy link
Owner

本文为博客迁移过来,原文链接: 事件重复绑定与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 比较容易误伤队友...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant