注册事件两种方式
<button>传统方法注册事件</button>
<button>方法监听注册事件</button>
<script>
var btns = document.querySelectorAll('button');
// 1. 传统方式注册事件
btns[0].onclick = function () {
alert('hi');
}
btns[0].onclick = function () {
alert('贝贝奇');
}
// 特点:注册事件的唯一性
// 同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数会覆盖前面注册的处理函数
// 2. 事件监听注册事件 addEventListener
// (1)里面的事件类型是字符串 必须加引号 而且不带on
// (2)同一个元素 同一个事件可以添加多个监听器(事件处理程序)
btns[1].addEventListener('click',function(){
alert('我是贝贝奇');
})
btns[1].addEventListener('click',function(){
alert('也是中路交警');
})
// IE9 之前不支持 可使用attachEvent 代替
// 特点:同一个元素同一个事件可以注册多个监听器
// 按照注册顺序依次执行
</script>
删除事件
<div>1</div>
<div>2</div>
<script>
var divs = document.querySelectorAll('div');
divs[0].onclick = function () {
alert('我是贝贝奇');
// 1. 传统方式删除事件
divs[0].onclick = null;
}
// 2. removeEventListener 删除事件
divs[1].addEventListener('click', fn);// 里面的fn不需要加小括号
function fn() {
alert('我是中路交警');
divs[1].removeEventListener('click',fn);
}
</script>
DOM事件流
事件流描述的是从页面接受事件的顺序
事件发生时会在元素节点之间按照特点的顺序传播,这个传播过程即DOM事件流
DOM事件流分为3个阶段:
1.捕获阶段
2.当前目标阶段
3.冒泡阶段
我们向水里扔一块石头,首先它会有一个下降的过程,这个过程可以理解为从
最顶层向事件发生的具体元素(目标点)的捕获过程;之后会产生泡泡,会在最低点
(最具体元素)之后漂浮到水面上,这个过程相当于事件冒泡
注意:
1.js代码种只能执行捕获或者冒泡其中一个阶段
2.onclick 和 attachEvent 只能得到冒泡阶段
3.addEventListener(type,listener,useCaptrue)第三个参数是true
表示在事件捕获阶段调用事件处理程序;如果是false(不写默认是false)
表示在冒泡阶段调用事件处理程序
4.实际开发中我们很少用事件捕获,我们更关注事件冒泡
5. 有些事件是没有冒泡的,比如 onblur,onfocus,onmouseenter,onmouseleave
6. 事件冒泡有时候会带来麻烦,有时候又会帮助很巧妙的做某些事件
<div class="father">
<div class="son">son</div>
</div>
<script>
// 1. 捕获阶段 如果addEventListener 第三个参数是 true 那么处于捕获阶段
// document -> html -> body -> father -> son
/* var son = document.querySelector('.son');
son.addEventListener('click',function(){
alert('son');
},true);
var father= document.querySelector('.father');
father.addEventListener('click',function(){
alert('father');
},true); */
// 2. 冒泡阶段 如果addEventListener 第三个参数是 false 那么处于冒泡阶段
// son -> father -> body -> html -> document
// 阻止事件冒泡 dom 推荐的标准 stopPropagation()
var son = document.querySelector('.son');
son.addEventListener('click', function (e) {
alert('son');
//e.stopPropagation(); // stop 停止 Propagation 传播
e.cancelBubble = true; // 非标准 cancel 取消 bubble 泡泡
}, false);
var father = document.querySelector('.father');
father.addEventListener('click', function () {
alert('father');
}, false);
document.addEventListener('click', function () {
alert('document');
});
</script>
事件对象
1. event 就是一个事件对象 写道我们监听函数的小括号里 当形参看
2. 事件对象只有有了事件才会存在,它是系统给我们自动创建的,不需要我们传递参数
3. 事件对象 是和我们事件一系列相关数据的集合 跟事件相关的 比如鼠标点击里面包含了
鼠标的相关信息 鼠标坐标等 ,如果是键盘事件里面就包含键盘事件的信息 比如 判断
用户按下哪个键
4. 这个事件对象我们可以自己命名 比如 event evt e
5. 事件对象也有兼容性问题 ie678 通过 window.event
// 事件对象
var div = document.querySelector('div');
div.onclick = function(e){
console.log(e);
// ie678 通过 window.event 获取
console.log(window.event);
// 兼容性的写法
// e = e || window.event;
}
div.addEventListener('click',function(e){
console.log(e);
})
常见事件对象和方法
常见事件对象的属性和方法
1. e.target 返回的是触发事件的对象(元素)
this 返回的是绑定事件的对象(元素)
区别: e.target 点击了哪个元素就返回哪个元素 this 哪个元素绑定了这个点击事件,那么就返回谁
var div = document.querySelector('div');
div.addEventListener('click',function(e){
console.log(e.target);
console.log(this);
});
var ul = document.querySelector('ul');
ul.addEventListener('click',function(e){
// 我们给ul绑定了事件 this 就指向ul
console.log(this);
console.log(e.currentTarget);
// e.target指向我们点击的那个对象 谁触发了这个事件 我们点击的是li e.target指向的就是li
console.log(e.target);
});
/*
了解兼容性
div.onclick = function(){
e = e || window.event;
var target = e.target || e.srcElement;
console.log(target);
}
跟this有个非常相似的属性 currentTarget ie678不认识
*/
事件对象阻止默认行为
<div>123</div>
<a href="http://www.baidu.com">百度</a>
<form action="http://www.baidu.com">
<input type="submit" value="提交" name="sub">
</form>
<script>
// 1. 返回事件类型
var div = document.querySelector('div');
div.addEventListener('click', fn);
div.addEventListener('mouseover', fn);
div.addEventListener('mouseout', fn);
function fn(e) {
console.log(e.type);
}
// 2. 阻止默认行为(事件)让链接不跳转 或者让提交按钮不提交
var a = document.querySelector('a');
/* a.addEventListener('click',function(e){
e.preventDefault(); // dom 标准写法
}); */
// 3. 传统的注册方式
a.onclick = function (e) {
// 普通浏览器 e.preventDefault(); 方法
// 低版本浏览器 ie678 returnValue 属性
/* 我们可以通过 return false 也能阻止默认行为 没有兼容性问题
特点:return 后面的代码不执行 而且只限于传统的注册方式 */
return false;
alert(11);
}
</script>
事件委派
事件委托的核心原理:给父节点添加侦听器,利用事件冒泡影响每一个子节点
<ul>
<li>知否知否,点我应有弹框在手!</li>
<li>知否知否,点我应有弹框在手!</li>
<li>知否知否,点我应有弹框在手!</li>
<li>知否知否,点我应有弹框在手!</li>
</ul>
<script>
var ul = document.querySelector('ul');
ul.addEventListener('click',function(e){
alert('知否知否,点我应有弹框在手!');
// e.target 得到我们点击的对象
e.target.style.backgroundColor = 'pink';
})
</script>
常见的鼠标事件
我是一段不愿意分享的文字
<script>
// 1. contextmenu 我们可以禁用右键菜单
document.addEventListener('contextmenu',function(e){
e.preventDefault();
});
// 2. 禁止选中文字 selectstart
document.addEventListener('selectstart',function(e){
e.preventDefault();
})
</script>
鼠标事件对象
<script>
// 鼠标事件对象 MouseEvent
document.addEventListener('click', function (e) {
// 1. client 鼠标在可视区的x和y坐标
console.log(e.clientX);
console.log(e.clientY);
// 2. page 鼠标在页面文档的x和y坐标
console.log(e.pageX);
console.log(e.pageY);
// 3. screen 鼠标在电脑屏幕的x和y坐标
console.log(e.screenX);
console.log(e.screenY);
});
</script>
跟随鼠标的天使案例
<style>
img {
position: absolute;
}
body{
height: 3000px;
}
</style>
<img src="images/angel.gif" alt="">
<script>
var img = document.querySelector('img');
document.addEventListener('mousemove', function (e) {
// 1.mousemove只要我们移动鼠标1px 就会触发这个事件
// 2.核心原理:每次鼠标移动,我们都会获得最新的鼠标坐标,把这个x和y坐标
// 作为图片的top和left就可以移动图片
img.style.left = e.pageX - 50 + 'px';
img.style.top = e.pageY - 40 + 'px';
})
</script>
常见的键盘事件
/* document.onkeyup = function(){
console.log('我弹起了');
} */
// 常用的键盘事件
// 1. keyup 按键弹起的时候触发
document.addEventListener('keyup', function () {
console.log('我弹起了');
})
// 2. keydown 按键按下的时候触发 能识别功能键 比如 ctrl shift 左右箭头
document.addEventListener('keydown', function () {
console.log('我按下了down');
})
// 3. keypress 按键按下的时候触发 不能识别功能键 比如 ctrl shift 左右箭头
document.addEventListener('keypress', function () {
console.log('我按下了press');
})
// 4. 三个事件的执行顺序 keydown -> keypress -> keyup
键盘事件对象
键盘事件对象中的keyCode属性可以得到相应健的ASCII码值
1. 我们的keyup 和keydown事件不区分大小写 a和A得到都是65
2. 我们的keypress事件区分字母大小写 a97和A得到65
document.addEventListener('keyup', function (e) {
console.log('up:' + e.keyCode);
// 我们可以利用keycode返回的ASCII码值赖判断用户按下了哪个键
if (e.keyCode == 65) {
console.log('你按下了a键');
} else {
console.log('你没有按下a键');
}
})
document.addEventListener('keypress', function (e) {
console.log('press:' + e.keyCode);
})
模拟京东案件输入内容
// 核心思路:检测用户是否按下了s键,如果按下s键,就把光标定位到搜索框
// 使用键盘事件对象里面的keyCode判断用户按下的是否是s键
// 搜索框获得焦点:使用js里面的focus()方法
<input type="text">
<script>
var serch = document.querySelector('input');
document.addEventListener('keyup',function(e){
//console.log(e.keyCode);
if(e.keyCode === 83){
serch.focus();
}
})
</script>
模拟京东快递单号查询
// 快递单号输入内容时,上面的大号字体盒子.box1显示 里面字号更大
// 表单检测用户输入:给表单添加键盘事件
// 同时把快递单号里面的值value获取过来给.box1盒子的innerHTML作为内容
// 如果快递单号为空,则隐藏.box1
<style>
body{
background-color: #cccccc;
}
.father {
width: 200px;
height: 200px;
margin: 100px auto;
}
.box1 {
display: none;
position: relative;
width: 200px;
height: 20px;
background-color: #ffffff;
margin-bottom: 3px;
border-radius: 5px;
font-size: 18px;
}
.box1::before{
content: '';
position: absolute;
top: 20px;
left: 12px;
border: 5px solid transparent;
border-top-color: #ffffff;
}
input {
width: 200px;
outline: none;
}
</style>
<div class="father">
<div class="box1"></div>
<input type="text" name="" id="" placeholder="请输入内容">
</div>
<script>
var div = document.querySelector('.box1');
var ipt = document.querySelector('input');
ipt.addEventListener('keyup',function(){
if(this.value == ''){
div.style.display = 'none';
}else{
div.style.display = 'block';
div.innerHTML = this.value;
}
})
// 注意:keydown和keypress在文本框的特点:当他们两个事件触发时候,文字还没有落入文本框
// 失去焦点隐藏盒子
ipt.addEventListener('blur',function(){
div.style.display = 'none';
})
// 获得焦点显示盒子
ipt.addEventListener('focus',function(){
if(this.value !== ''){
div.style.display = 'block';
}
})
</script>