js事件是js中非常重要的知识点。js与用户的很多互动都需要事件来完成。比如:
1、点击登录按钮完成登录的click点击事件
2、输入框失焦校验的blur失焦事件
3、鼠标移入移出的mouseover和mouseout事件等等。
下面通过代码来展示在dom元素上绑定一个点击事件:
<body>
<input type='button' value="请点击!" onClick="clickHandler">
<script>
function clickHandler(){
console.log('clicked')
}
</script>
</body>
第二种绑定事件的方式是听过js事件监听来给元素注册事件:
<body>
<input id="input" type='button' value="请点击!">
<script>
var input = document.getElementById('input')
input.addEventListener('click',()=>{
console.log('clicked')
})
</script>
</body>
两种方法都很简单,值得小心的是,以点击事件为例:在dom中直接绑定事件,用的是onClick属性,而js绑定事件是click,没有on
1)、onClick点击事件
2)、onFous获得焦点和onBlur失去焦点事件
3)、onMouseover和onMouseout事件
4)、onKeyDown和onKeyUp事件
更多事件可自行查阅api文档
下面还是通过代码来演示:
<body>
<div id="div1">
<p id="p1">第一个p</p>
<p>第二个p</p>
<p>第三个p</p>
<p>第四个p</p>
<p>第五个p</p>
</div>
<script>
// 这里为了方便给元素注册事件,简单封装了一个添加事件监听的函数
function addEvent(ele,eventType,callback){
ele.addEventListener(eventType,callback)
}
var div1 = document.getElementById('div1')
var pList = document.getElementsByTagName('p')
// 循环为每个p注册点击事件
for(let i = 0;i<pList.length;i++){
addEvent(pList[i],'click',event=>{
console.log(`第:${i}个p标签被点击了`)
})
}
// 为p的父元素div1注册点击事件监听
addEvent(div1,'click',event=>{
console.log('div1 =====>clicked'+'====target===>'+event.target)
})
// 为body注册点击事件
addEvent(document.body,'click',event=>{
console.log('body*****clicked****target*****'+event.target)
})
</script>
</body>
当我们点击任意的p元素时,输出结果如下:
可以看到,当点击第二个p时,不仅触发了p本身的点击事件,还触发了p的父元素div1和div1的父元素body的点击事件,示意图如下:
如果我们想阻止事件冒泡呢,只需要在当前目标上加上该方法: event.stopPropagation()
此时对比代码执行结果:
此时,div1和body的点击事件没有被触发。
事件委托主要利用的是事件冒泡机制,通过事件传递,把本应该绑定在子元素上的事件,绑定到父元素中,但是父元素中这么多子元素,怎么区分是哪一个呢? 主要是通过event.target属性来获取当前触发事件的子元素,下面以代码为例:
<body>
<div id="div1">
<p>第一个p标签</p>
<p>第二个p标签</p>
<p>第三个p标签</p>
<p>第四个p标签</p>
<p>第五个p标签</p>
<p>第六个p标签</p>
</div>
<script>
var div1 = document.getElementById('div1')
div1.addEventListener('click',(event)=>{
// 获取当前实际触发的元素
var target = event.target
alert(target.innerHTML)
})
</script>
</body>
面试题:封装一个公共函数,用于事件监听:
<body>
<div id="div1">
<p>这是p1</p>
<p>这是p2</p>
<p>这是p3</p>
<p>这是p4</p>
<p>这是p5</p>
<p>这是p6</p>
<p>这是p7</p>
<p>这是p8</p>
<p>这是p9</p>
</div>
<script>
/**
* @description: 封装的公共的函数
* @param {elem}:dom元素,给哪个dom元素添加事件
* @param {type}:事件类型
* @param {selecter}:选择器,根据这个参数判断是否需要事件代理
* @param {fn}:执行函数
* @return:
*/
function bindEvent(elem, type, selecter, fn) {
if (fn == null) {
//判断一下selecter这个参数是否存在
fn = selecter
selecter = null
}
elem.addEventListener(type, function (e) {
//代理
if (selecter) {
//代理
var target = e.target
if (target.matches(selecter)) {
//这里target代表出发事件的节点,是否和你传的selecter相匹配
fn.call(target, e)
}
} else {
// 普通注册
fn.call(target,e)
}
})
}
var div1 = document.getElementById('div1')
// 注意,这里的函数不能使用箭头函数,箭头函数没有this指向,会向上找到window
bindEvent(div1,'click','p',function(e){
e.preventDefault()
console.log(this.innerHTML)
})
</script>
</body>
关于target.matches()用法参考:Element.matches()用法