介绍下事件流:
三个阶段:捕获、目标、冒泡
冒泡,字面上理解,就是从下往上冒泡,咕噜咕噜~可以理解成从具体节点到不具体节点的事件流(addEventListener
默认监听选项)
捕获,与冒泡相反,就是从大节点一直往下获取事件流,直到具体节点
事件委托(事件委托 是 别名)
如果你想要在大量子元素中单击任何一个都可以运行一段代码,您可以将事件监听器设置在其父节点上,并让子节点上发生的事件冒泡到父节点上,而不是每个子节点单独设置事件监听器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| $('.top_wrapper a').each(function (index,item) { let aLink = $(item).attr('href'); if (!aLink.includes('?')) { aLink += '?'; } if (coupon) { aLink +=`&coupon=${coupon}`; $(item).attr('href',aLink ); } if (qd) { aLink +=`&qd=${qd}`; $(item).attr('href',aLink ); } $(item).attr('href', aLink); })
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| <ul id="list"> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ul> var list = document.querySelector('#list') list.addEventListener('click',function (e){ if(e.target.tagName === 'LI'){ console.log('当前元素事件触发成功') } })
|
事件监听
addEventListener(eventName,function,bool)
// eventName事件名 function是触发的函数 bool为true时是捕获 默认是false冒泡
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <ul id="list"> <li> <div>div</div> </li> <li>2</li> <li>3</li> <li>4</li> </ul> <script> var list = document.querySelector('#list') list.addEventListener('click', function (e) { let li = e.target.closest('li'); if (!li) return; if(!list.contains(li)) return; console.log(li) }) </script>
|
事件绑定
(1) 内联 (优先级最高)
1
| <input type="button" value="按钮" onclick="alert(1);">
|
(2) 对象.事件
1 2 3 4 5 6 7
| <input type="button" value="按钮">
var bt = document.getElementsBytagname("input")[0] bt.onclick = function(){ alert(2) }
|
以上两种方式只能绑定一个事件
(3) addEventListener
1 2 3 4 5 6 7 8
| <input type="button" value="按钮">
var bt = document.getElementsBytagname("input")[0]
bt.addEventListener('click',function(){
})
|
event.stopPropagation: 阻止捕获和冒泡阶段中当前事件的进一步传播。
event.preventDefault: 阻止默认行为,调用了后就会取消事件的执行。
知识点:
事件绑定
事件冒泡
事件代理
QA:
编写一个通用的事件监听函数
有时候在事件处理函数内部,您可能会看到一个固定指定名称的参数,例如 event,evt 或简单的 e。
这被称为事件对象,它被自动传递给事件处理函数,以提供额外的功能和信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| function bindEvent(elem, type, selector, fn) { if (fn == null) { fn = selector selector = null } elem.addEventListener(type, e => { const target = e.target if (selector) { if(target.matches(selector)) { fn.call(target, event) } else { fn.call(target, event) } } }) } const btn1 = document.getElementById('btn1') btnEvent(btn1, 'click', 'button', event => { event.preventDefault() alert('clicked') })
|
描述事件冒泡的流程
基于DOM 树形结构, DOM 树的深层级 往 浅层级 的事件响应,就是 事件冒泡
事件代理 的机制也是 事件冒泡
1 2 3 4 5 6 7 8 9 10
| const p1 = document.querySelector('#p1') const body = document.body bindEvent(p1, 'click', (e) => { e.stopPropagation() alert('子') }) bindEvent(body, 'click', (e) => { alert('父') })
|
无限下拉的图片列表,如何监听每个图片的点击?
参考:
segment
javascript.info
event.stopPropogation
事件 MDN