事件高级
注册事件
传统方式
方法监听注册方式
监听对象.addEventListener()是一种方法。同一元素同一时间注册多个事件。addEvenListener(type,listener,useCapture)
btn[1].addEventListener('click',function(){
alert('牛逼')
})
btn[1].addEventListener('click',function(){
alert('牛逼++')
})
//可以多个监听器
删除事件
有传统方式和注册方式删除
<div>1</div>
<div>2</div>
<div>3</div>
<script>
var div = document.querySelectorAll('div');
div[0].onclick= function(){
alert('11');
// 传统方式解绑
div[0].onclick = null;
}
div[1].addEventListener('click',fn)
function fn(){
alert('22');
// 注册事件删除
div[1].removeEventListener('click',fn)
}
</script>
DOM事件流
事件流描述的是从页面中接受事件的顺序
事件发生时回在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流
js代码中只能执行捕获或者冒泡其中的一个阶段。
捕获阶段 如果addEventListener()第三个参数是ture那么处于捕获阶段。
冒泡阶段 如果addEventListener()第三个参数是ture或省略,那么处于捕获阶段。
捕获跟冒泡都是按顺序来的,不能越级。
<body>
<div class="fa">
<div class="son"></div>
</div>
</body>
<script>
// 捕获阶段:document-> html ->body->fa->son
var son = document.querySelector('.son');
son.addEventListener('click',function(){
alert('11');
},true);
var fa = document.querySelector('.fa');
fa.addEventListener('click',function(){
alert('22');
},true);
</script>
该例子时,点击子元素,会先弹出父元素的警告框,即22.再弹出11,因为点击son必须经过fa。
相反,在冒泡阶段,只点了son,fa和document都会事件响应,往上递增,此为冒泡。
事件对象
在触发DOM上的某个事件时,会在事件处理程序函数中会产生一个事件对象event,这个对象中包含着所有与事件有关的信息。包括导致事件的元素、事件的类型以及其他与特定事件相关的信息。
就是事件对象在出发时间后产生,包含了事件的基本信息,鼠标位置,键盘位置等等。
btn.addEventListener("click", function(event) {
alert(event.type); //"click"
}, false);
- even就是一个事件对象,写到我们监听函数的小括号里,当形参传入。
- 事件对象只有有了事件才会存在,她是系统给我们自动创建的
- 事件对象时我们时间的一系列数据的集合
常见事件对象的属性和方法
e.target返回触发事件的对象,与this类似,但this返回绑定事件的对象。以下例子帮助理解👇
<ul>
<li>123</li>
<li>123</li>
<li>123</li>
</ul>
</body>
<script>
var ul = document.querySelector('ul');
ul.addEventListener('click',function(e){
// 给ul绑定了事件,指向ul
console.log(this);
// e.target指向点击的对象li
console.log(e.target);
})
</script>
e.type返回事件属性,click或onmouseout等等。
e.preventDefault dom标准写法(事件,对监听器使用),阻止默认行为,如不让链接跳转,提交按钮不提交。
另,可以用return:false;也能阻止默认行为,但只针对于传统注册方式。οnclick=function(){};之类。而且return:false后面的代码全都不生效
e.stopPropagation 阻止冒泡,不会产生事件延续的现象。
<script>
// 冒泡阶段:son->fa->body->html->document
var son = document.querySelector('.son');
son.addEventListener('click',function(){
alert('11');
e.stopPropagation();
//只阻止son的冒泡
},false);
var fa = document.querySelector('.fa');
fa.addEventListener('click',function(){
alert('22');
},false);
</script>
事件委托
原理: 不是每个子节点都要单独设置事件监听器,而是事件监听器设置在父结点上,利用冒泡影响设置每一个子节点 。
eg:给ul注册点击事件,利用事件对象的target来找到当前点击的li,因为点击li,事件会冒泡到ul上,ul有注册事件,就会触发事件监听器。
了解:
禁止右键和禁止选中:一般用在文字内容有特殊需求时
<script>
// 禁用右键菜单
document.addEventListener('contextmenu',function(e){
e.preventDefault();
})
// 禁用选中文字
document.addEventListener('selectstart',function(e){
e.preventDefault();
})
</script>
常用鼠标事件
鼠标事件对象
<script>
document.addEventListener('click',function(e){
// 可视区的x,y坐标
console.log(e.clientX);
console.log(e.clientY);
// 文档区的x,y坐标
console.log(e.pageX);
console.log(e.pageY);
// 屏幕的x,y坐标 算上侧边栏那些的距离
console.log(e.screenX);
console.log(e.screenY);
})
</script>
案例:让一个小圆点跟随鼠标移动
<script>
// 样式中必须加绝对定位,不然定位无效
var div = document.querySelector('div');
document.addEventListener('mousemove',function(e){
// 要加上单位px
div.style.left = e.pageX +'px';
div.style.top = e.pageY +'px';
})
</script>
常用键盘事件
与鼠标事件差不多,应用不同
三个事件有执行顺序:keydown->keypress->keyup
键盘事件对象
keyCode可以获取相应键的ascll码。
keyPress事件区分大小写,而keyUp和keyDown不区分大小写,a,A都是65,得到是A的ascll码
案例:快捷键进入搜索框
var search = document.querySelector('input');
document.addEventListener('keyup',function(e){
//此处设置keyup是因为键盘按键弹起后再执行事件,避免按键按下的同时输入进文本框
if(e.keyCode === 83){
search.focus();
}
})
案例:模拟京东查询单号,即放大文本框内的内容
<div class="search">
<input type="text" value="请输入" />
<div class="bigger"></div>
</div>
<script>
var big = document.querySelector(".bigger");
var input = document.querySelector("input");
input.addEventListener('focus',function(){
if(input.value === '请输入')
input.value = '';
//聚焦且有内容时,放大的框显示
if(this.value !== ''){
big.style.display = 'block';
}
})
input.addEventListener('blur',function(){
//失去焦点时则隐藏放大框
big.style.display = 'none';
//检测是否重置默认值
if(input.value ===''){
input.value = '请输入'
}
})
input.addEventListener("keyup", function (e) {
if (this.value == "") {
big.style.display = "none";
} else {
// 输入内容则显示且赋值
big.style.display = "block";
big.innerHTML = this.value;
}
});
</script>
另:上文快捷键案例用了keyup,文本框无内容显示,但是这里也是keyup,文本框却有内容显示?
原因是两者目的不同
- 快捷键调取文本框,是为了调取而不输入内容,所以在没有聚焦情况下不会输入,keyup也不会影响快捷键会输入进文本框。
- 但查询单号功能主要是为了输入,是在鼠标聚焦后的,所以会输入。如果用keydown和keypress,他们按下后事件生效,但是字体却还没有落入文本框中。按下时,事件触发,判断盒子是否显示,但文本框内没文字,所以盒子不显示,事件执行完后字才进去。
而keyup是事件触发时,文字已经在文本框里了,因为是按键弹起,按键弹起前就显示文字了。
(还学到了placeholder,亏我还写了js控制焦点默认文本消失😥)