<!-- 事件高级 -->
<!-- 注册事件 : 有两种注册事件的方式(传统方式和方法监听注册方式) -->
<!-- 传统注册方式:引用on开头的事件 比如onclick ; 特点:注册事件的唯一性 同一个元素同一个事件只能设置一个函数,最后注册的 处理函数会覆盖前面注册的处理函数-->
<!-- 方法监听注册方式(移动端使用较多): w3c标准 推荐方式 ; addEventListener()他是一个方法 ; ie9之前的ie不支持此方法,可以使用attahEvent()代替 ; 特点:同一个元素同一个事件可以注册多个监听器(监听处理函数) 按注册顺序依次执行-->
<!-- <button>传统注册事件</button>
<button>方法监听注册事件</button>
<button>ie9之前的ie</button>
<script>
//传统注册事件 无兼容问题
var btn = document.querySelectorAll('button');
btn[0].onclick = function(){
alert(11);
}
//事件监听注册事件
btn[1].addEventListener('click',function(){ //里面的事件类型是字符串,必须加引号,且没有on
alert(22);
})
btn[1].addEventListener('click',function(){ //同一个事件可以添加多个侦听器,顺序执行
alert(33);
})
//attachEvent 事件监听方式(一般不使用) ie9之前的ie才能支持
btn[2].attachEvent('onclick',function(){
alert(44);
})
//所有兼容:注册事件兼容性解决方案(了解)
</script> -->
<!-- 删除事件(解绑事件) -->
<!-- <div>1</div>
<div>2</div>
<div>3</div>
<script>
var divs = document.querySelectorAll('div');
divs[0].onclick = function(){
alert(11);
divs[0].onclick = null; //传统方式 : eventTarget.onclick = null
}
divs[1].addEventListener('click',fn); //如果要考虑后面会删除函数的话,就要把处理函数写在外面 fn在这里不需要加小括号
function fn(){
alert(22);
divs[1].removeEventListener('click',fn); //方法监听注册方式 : eventTarget.removeEventListener(type,listener[,useCapture]);
}
divs[2].attachEvent('onclick',fn1);
function fn1(){
alert(33);
divs[2].detachEvent('onclick',fn1); //detachEvent('',)方法
}
//删除事件也有兼容性方案
</script> -->
<!-- DOM事件流 -->
<!-- 事件流:从页面接受事件的顺序 -->
<!-- DOM事件流:事件发生时会在元素节点之间按照一定的顺序传播,这个传播过程就叫DOM事件流 -->
<!-- DOM事件流分为3个阶段 : 1.捕获阶段(最顶层传到当前事件 上往下) 2.当前目标阶段 3.冒泡阶段(从当前传到最顶层 从下往上) -->
<!-- <div class="father">
<div class="son">son盒子</div>
</div>
<script>
//dom事件流三个阶段
//1.JS代码中只能执行捕获或者冒泡的其中一个阶段
//2.onclick 和 attachEvent(ie) 只能得到冒泡阶段
var son = document.querySelector('.son');
son.addEventListener('click',function(){
alert('son');
},true); //如果 addEventListener 的第三个参数为 true 则表示处于捕获阶段
var father = document.querySelector('.father');
father.addEventListener('click',function(){
alert('father');
},true); //捕获阶段 document -> html -> body -> father -> son 由于处于捕获阶段,所以此处虽然father的事件写在后面,但是执行的时候是先执行father
//冒泡阶段(实际开发中常关注) 有些事件没有冒泡,比如 onblur,onfocus,onmouseenter,onmouseleave 事件冒泡有时会带来麻烦,但有时也会帮助很巧妙的某些事件,后面再了解
var father = document.querySelector('.father');
father.addEventListener('click',function(){
alert('father'); //如果 addEventListener 的第三个参数为 false 或者 省略 则表示处于冒泡阶段
});
var son = document.querySelector('.son');
son.addEventListener('click',function(){
alert('son');
},false); //冒泡阶段 son -> father -> body -> html ->document 由于处于冒泡阶段,所以此处先执行son
document.addEventListener('click',function(){
alert('document');
}); //最后弹出document
</script> -->
<!-- 重点!!⭐事件对象 -->
<!-- <div>123</div>
<script>
var div=document.querySelector('div');
div.onclick = function(event){
console.log(event); //event就是一个事件对象,它写在函数小括号里 ,可以当形参来看,只是它是系统自动创建,不需要我们自己传参, 它包含了事件的一系列相关信息,比如此处的event包含了鼠标点击的坐标等 且只有事件存在时才会有事件对象存在
}
div.addEventListener('click',function(e){}); //事件对象可以自己命名,一般取名为 e 、evt 事件对象也有兼容性问题 在ie678里 只认识window.event这个事件对象写法
//但有兼容性写法 e = e || window.event 意思是事件对象可能是e,也可能是window.event
div.onclick = function(e){
e=e ||window.event;
console.log(e); //这样每个浏览器就都可以识别了
}
</script>
常见事件对象的属性和方法
<div>123</div>
<ul>
<li>12</li>
<li>12</li>
<li>12</li>
</ul>
<a href="http://www.baidu.com">百度</a>
<input type="submit" value="提交">
<script>
//1.e.target(标准) 返回触发事件的元素 ie678不支持,只支持e.srcElement(非标准)
/* var div = document.querySelector('div');
div.addEventListener('click',function(e){
console.log(e.target); //返回div
})
//2.e.target 与 this 的区别
var ul =document.querySelector('ul');
ul.addEventListener('click',function(e){
console.log(this); //返回ul (返回绑定事件的元素 , 此处为 ul)
console.log(e.target); //返回li (返回触发事件的元素,此处为 li ,因为鼠标点击的是 li )
})
//了解(currentTarget 与 this 属性相似 ie678不支持) */
//返回事件类型 type
/* var div = document.querySelector('div');
div.addEventListener('click',function(e){
console.log(e.type); //返回click
})
div.addEventListener('mouseover',function(e){
console.log(e.type); //mouseover
})
*/
//阻止默认行为(事件) 阻止链接跳转 或者不让按钮提交(比如想在它跳转之前做一些事或者满足某些条件才跳转)
/* var a=document.querySelector('a');
a.addEventListener('click',function(e){
e.preventDefault(); //DOM标准写法
})
a.onclick = function(e){
e.preventDefault(); //普通浏览器写法
e.returnValue; //低版本写法 这是一个属性 ie678
//我们也可以利用 return false 这个没有兼容性问题
return false; //特点:遇到 return 后,之后的代码就不执行了
alert(11); //这个就不会执行了
} */
//阻止冒泡 !!重点!面试常考 ⭐
//标准写法: stopPropagation(); 停止传播 也有兼容性问题 // ie678 :e.cancleBubble=true;(非标准)
var son = document.querySelector('.son');
son.addEventListener('click',function(e){
alert('son');
e.stopPropagation(); //不再弹出 father了
},false);
var father = document.querySelector('.father');
father.addEventListener('click',function(){
alert('father'); //father没有设置阻止冒泡,点击它之后document依然会弹出来
},false);
document.addEventListener('click',function(){
alert('document');
});
</script> -->
<!-- 事件委托(代理、委派) -->
<!-- 事件委托的原理(!重点!面试常问⭐): 不是每个子节点单独设置监听器,而是把事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点 -->
<!-- 比如:ul里有许多小li 我们给ul注册点击事件。然后利用事件对象的 target 来找到当前点击的li ,因为点击li,事件会冒泡到ul上,ul有注册事件,就会触发事件监听器 -->
<!-- 事件委托的作用 : 我们只操作了一次DOM,提高了程序的性能 -->
<ul>
<li>知否知否,应是绿肥红瘦</li>
<li>知否知否,应是绿肥红瘦</li>
<li>知否知否,应是绿肥红瘦</li>
<li>知否知否,应是绿肥红瘦</li>
<li>知否知否,应是绿肥红瘦</li>
</ul>
我是一段不愿意分享的文字
<script>
/* var ul = document.querySelector('ul');
ul.addEventListener('click',function(e){
alert('知否!'); //只点击每个li 也可以弹出
e.target.style.backgroundColor='pink'; //利用target可以定位当前操作对象是谁,改变当前对象的背景颜色
})
//常用鼠标事件
//1.禁用鼠标右键菜单 contextmenu 主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单
document.addEventListener('contextmenu',function(e){
e.preventDefault();
})
//2.禁止鼠标选中(selectstart开始选中)
document.addEventListener('selectstart',function(e){
e.preventDefault(); //不能选中文字了
}) */
//鼠标事件对象 MouseEvent
//1.clientX clientY 是相当于可视区域的 即使页面很长,点击的坐标依然只相对于可视化区域(也就是浏览器窗口可视区上框和左框)
/* document.addEventListener('click',function(e){
console.log(e.clientX);
console.log(e.clientY);
console.log('______');
})
//2.page(更常用) 鼠标在页面文档的x和y坐标 ie9以上支持
document.addEventListener('click',function(e){
console.log(e.pageX);
console.log(e.pageY);
}) */
//键盘事件
//常用键盘事件: onkeyup 某个按键被松开时触发 ; onkeydown 某个键盘按键被按下时触发 ; onkeypress 某个键盘按键被按下时触发
//1.onkeyup 某个按键被松开时触发
/* document.onkeyup = function(){
console.log('我弹起了');
} */
/* document.addEventListener('keyup',function(){
console.log('我弹起了');
})
//2.onkeydown 某个键盘按键被按下时触发
document.addEventListener('keydown',function(){
console.log('我按下了down');
})
//3.onkeypress 某个键盘按键被按下时触发 他不会识别功能键,比如 ctrl shift 左右箭头等等
document.addEventListener('keypress',function(){
console.log('我按下了press');
}) //4.三个顺序:keydown - keypress - keyup */
//键盘事件对象
document.addEventListener('keyup',function(e){
console.log('up:' + e.keyCode); //keyCode属性可以得到事件的按下的具体哪个键对应的ASCII码 可以判断用户按下哪个键
if(e.keyCode === 65){
alert('你按下了a键');
}else{
alert('你么有按下a键');
}
}) //注意:!keyup 和 keydown 事件是不区分大小写的 比如按下a和A返回的都是 65
//如果要区分大小写,可以用keypress
document.addEventListener('keypress',function(e){
console.log('press:' + e.keyCode); //a得到97 A得到65
})
</script>
案例:
<!-- 案例:天使图片跟随着鼠标的移动而移动 -->
<!-- 分析:1.鼠标不断地移动,使用鼠标移动事件:mouseove 2.在页面中移动,给document添加移动事件 3.图片要移动距离,而且不占位置,使用绝对定位 4.核心原理:每次鼠标移动,我们都会获取最新的鼠标坐标,把这个x和y坐标作为图片的top和left值就可以移动图片 -->
img{
position: absolute;
top: 2px;
}
</style>
</head>
<body>
<img src="image/angel.gif" alt="">
<script>
var pic = document.querySelector('img');
document.addEventListener('mousemove',function(e){
//只要鼠标移动就会触发这个事件
var x = e.pageX;
var y = e.pageY;
// console.log(x,y);
//把坐标给图片
pic.style.left=x - 50 + 'px'; //千万别忘了加单位,否则没有效果
pic.style.top=y -40 + 'px';
})
</script>
<!-- 案例:模拟京东按键按下内容(避免每次用鼠标去点搜索框麻烦,设置了只要输入 s 键就可以自定定位到搜索框里) -->
<!-- 核心思路:检测用户是否按下 s 键 ,如果按下了s 键,就把光标定位到搜索框里 ;
使用keyCode判断用户按下的键 ; 搜索框获得焦点:使用js里的 focus()方法 -->
<input type="text">
<script>
var search = document.querySelector('input');
document.addEventListener('keyup',function(e){ //在这里使用 keydown的话会把按下的内容一起输入到输入框中,为避免这种情况,这里最好使用 keyup ,这样在按键弹起时才触发,就不会把内容显示进去了
if(e.keyCode === 83){
search.focus(); //这个方法就是获得焦点的意思
}
})
</script>
<!-- 案例:模拟京东快递单号查询 -->
<!-- 要求:当我们在文本框输入内容时,文本框上面自动显示大字号的内容 -->
<!-- 分析:1.快递单号输入内容时,上面的大号字体盒子(con)显示(这里面的字号更大) 2.表单检测用户输入:给表单添加键盘事件 3.同时把快递单号里面的值(value)获取过来赋值给con盒子(innerHTML)作为内容 4.如果快递单号里面的内容为空,则隐藏大号字体(con)盒子-->
<style>
*{
padding: 0;
margin: 0;
}
.search{
width: 200px;
height: 200px;
margin: 100px auto;
position: relative;
outline: none;
}
.jd{
outline: none;
}
.con{
width: 170px;
line-height: 20px;
font-size: 18px;
color: #333;
border: 1px solid rgba(0, 0, 0, 0.2);
box-shadow: 0 2px 4px rgb(0, 0, 0,0.2);
padding: 5px 0;
position: absolute;
top: -40px;
display: none;
}
.con::before{ /* 小三角样式 */
content: '';
width: 0;
height: 0;
position: absolute;
top: 30px;
left: 20px;
border: 8px solid rgb(0, 0, 0);
border-style: solid dashed dashed;
border-color: #fff transparent transparent;
}
</style>
</head>
<body>
<div class="search">
<div class="con">123
</div>
<input type="text" placeholder="请输入您的快递单号" class="jd">
</div>
<script>
var con = document.querySelector('.con');
var jd = document.querySelector('.jd');
jd.addEventListener('keyup',function(){ //在此处不用 keydown和keypress是因为,按键按下的一瞬间就触发事件了,此时文本还未输入文本框就已经执行事件了,所以结果会少一个数字的显示
// console.log('输入内容');
if (this.value == ''){
con.style.display = 'none'; //当内容为空时,把上面的盒子隐藏起来
}else{
con.style.display = 'block';
con.innerHTML = this.value;
}
jd.addEventListener('blur',function(){ // 当文本框失去焦点时con盒子隐藏起来
con.style.display = 'none';
})
jd.addEventListener('focus',function(){ //当文本框获得焦点时,且有内容时,就显示 con 盒子
if (this.value !== ''){
con.style.display ='block';
}
})
})
</script>