目录
事件委托(事件代理)
键盘事件
编辑e.keycode
京东快递单号查询
页面加载事件
定时器setTimeout
清除定时器
监听事件:
传统的onclick对于后面的注册事件会覆盖前面的注册事件
方法监听注册方式:addEventListener()
t.addEventListener('click',function(){
alert(22);})
注意:type事件类型字符串 click mouseover不用on
删除事件
removeEventListener()
var divs = document.querySelectorAll('div');divs[1].addEventListener('click',fn);function fn() {alert(22);divs[1].removeEventListener('click',fn);}
在移除事件里不能用匿名函数,不然移除出错
var divs = document.queryselectorall('div')
divs[0].onclick=function() {alert(11);divs[0].onclick=null;//传统方式解除绑定
}
dom事件流
从页面接受事件的顺序
var son = document.querySelector('.son')
son.addeventlistener('click', function(){alert('son')},true);var father = document.querySelector('.father')
son.addeventlistener('click', function(){alert('father')},true);
第三个参数决定是冒泡(顺序为son,father)还是捕获(顺序为father,son),为true代表捕获
解决问题:只点击了son为何father和document都弹出了
更关注事件冒泡,有些事件没有冒泡,比如onblur,onfocus,onmouseenter,onmouseleave
事件对象
var div = document.queryselector('div')
div.onclick = function(event) {console.log(event);
}
1 event就是一个事件对象, 写到监听函数小括号里面 当形参来看
2 事件对象只有有事件才会存在,系统自动创建的不需要传递参数
3 事件对象是 事件一系列数据集合 和事件相关 比如鼠标点击就包含鼠标相关信息,鼠标坐标;如果是键盘事件里面包含键盘事件信息:判断用户按下哪个键
兼容性处理:
div.onclick = function(e) {console.log(e);console.log(window.event);e = e || window.event;//对于678,不认识e返回undefined但是认识window.eventconsole.log(e);
}
e.target:返回触发的元素
this:返回绑定的元素
var ul = document.queryselector('ul');
ul.addEventListener('click', function(e){console.log(this);//绑定的是ulconsole.log(e.target);//点击的对象,点击的是li,指向的就是li
})
e.srcElement (678 又不识别target)
//整体兼容性处理
div.onclick = function(e) {e = e || window.event;var target = e.target || e.srcElement;console.log(target);
console.log(e.type);
}
this相似的ie 9属性:currentTarget
//阻止默认行为,让链接不跳
a.addEventListener('click', function(e){e.preventDefault();
})a.onclick=function(e){e.preventDefault();//低版本浏览器,e.returnValue(这是属性,上面的是方法)return false;//这样也行没有兼容性问题
//但是从return开始后面的代码都不执行!而且只限制于传统的事件方式
}
阻止冒泡:e.stopPropagation()
怎么阻止冒泡:
1 获得son元素,2 添加事件 3 在事件里阻止冒泡
下述代码有问题,点击son确实没有冒泡,但是点击father还会冒泡到document
var son = document.queryselector('.son')
son.addeventlistener('click', function(e)) {alert('son');e.stopPropagation();e.cancelBubble = true;}, false);
//false是在冒泡阶段var father = document.querySelector('.father');
father.addEventListener('click', function() {alert('father');
},false);document.addEventListener('click', function() {alert('document');
});
事件委托(事件代理)
不要给每个子节点设置事件监听器,而是事件监听器设置在父节点上,利用冒泡原理影响设置每个子节点(重要!!)
<ul><li>你是猪</li><li>你是猪</li><li>你是猪</li><li>你是猪</li><li>你是猪</li></ul><script>// 给父节点添加监听,利用事件冒泡影响每一个子节点var ul = document.querySelector('ul');var sh = document.querySelectorAll('li');ul.addEventListener('click', function (e) {// alert('you r pig');// e.target得到点击的对象for (var i = 0; i < sh.length; i++)sh[i].style.backgroundColor = '';//差点错在画蛇添足写了个nonee.target.style.backgroundColor = 'pink';//关键就在这,利用冒泡使得点击li时候由于上级ul绑定了alert所以每点击一个li都会弹出弹框});</script>
相当于委托给父节点
preventDefault()阻止默认事件发生
document.addEventlistener('selectstart', function(e){e.preventDefault();//阻止默认事件发生,这里阻止control cv
})
鼠标事件:
<script>document.addEventListener('click', function(e){console.log(e.clientX);console.log(e.clientY);// 窗口能不能滚动无关,都是可视窗口里的坐标console.log(e.pageX);console.log(e.pageY);//和滚动有关,相对页面来讲})</script>
就是右下角那个的坐标,相对于整个框框(clientX)
键盘事件
<script>document.onkeyup=function() {console.log('弹起');}document.addEventListener('keydown', function(){console.log('按下');//如果一直按着数字1,这个事件就会不断触发,松开手就会触发弹起事件})document.addEventListener('keypress', function(){console.log('按下press');//和keydown一样,除了不识别功能键//三个事件执行顺序:先keydown再keypress再keyup})</script>
三个事件执行顺序:先keydown再keypress再keyup
e.keycode
得到事件的ascii码值
检测用户是否按了s,如果按了就定位到搜索框里//btn.focus();
使用键盘事件对象里keycode判断用户按是否是s//e.keycode===83
搜索框获得焦点:js里的focus方法
<body><input type="text" name="" id=""><script>var btn = document.querySelector('input');document.addEventListener('keyup',function(e){//这里触发最好用keyup,在键盘弹起时候触发,否则s也会写进去if(e.keycode===83){btn.focus();}})</script>
</body>
注意第五行是document.addEventListener,而不是btn.addEventListener
是需要在全局上监听的,不然按s没有效果
复习css里的在框框上添加三角形类似对话框:
.con::before {content:'';width:0;height:0;position:absolute;top:28px;left:18px;border:8px solid #000;border-style:solid dashed dashed;border-color:#fff transparent transparent;
}
1 对于增加装饰而言需要content但是为空
2 border-style分别上右下左,dashed虚线
京东快递单号查询
以及复习三角对话框css的实现
为何用keyup而不是keydown或者keypress
keydown和keypress都在文字还没落入文本框时候就触发事件立刻执行代码,字母还没输入,是空的,所以按下的时候盒子先隐藏了;当代码执行完毕,数字才输入结束
keypress除此之外还有个问题,不识别delete键
第二个功能:获得焦点时,显示大盒子;没有焦点时,隐藏大盒子
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>* {margin: 0;padding: 0;}/* 一般不用设置高度,让他根据内容自适应 */.search {position: relative;width: 178px;margin: 100px;}/* 上右下左100px外边距 */.con {display: none;position: absolute;top: -40px;width: 171px;border: 1px solid rgba(0, 0, 0, .2);box-shadow: 0 2px 4px rgba(0, 0, 0, .2);/* box-shadow 不会影响元素的布局,即它不会占用实际的页面空间 */padding: 5px 0;font-size: 18px;/* 块级元素的高度会自动适应其包含的内容的高度 */line-height: 20px;color: #333;}/* 1 rgba前三个表示red green blue,都为0表示黑色,.2透明度为20%
2 box-shadow :阴影的水平偏移,垂直偏移(阴影位于下方),模糊半径,3,4px轻微,10px强烈表示模糊程度,阴影颜色,透明值越小阴影越淡 */.con::before {content: '';width: 0;height: 0;position: absolute;top: 28px;/* 其顶部边缘相对于 .con 元素的顶部下移了 28px */left: 18px;border: 8px solid #000;border-style: solid dashed dashed;border-color: #fff transparent transparent;}/* 先确定位置再写高度,最后border和shadow */</style>
</head><body><div class="search"><!-- 通常定位是根据已定位祖先元素进行定位的 --><div class="con"></div><!-- 这个盒子需要显示和隐藏需要获取 --><input type="text" placeholder="请输入您的快递单号" class="jd"><!-- 检测用户有没有按下,也要获取 --><!-- 占位符placeholder文本通常是灰色的,并在用户开始输入时自动清除。 --></div><script>var con = document.querySelector('.con');var jd_input = document.querySelector('.jd');jd_input.addEventListener('keyup', function () {// console.log('输入内容');// 将当前文本框盒子内容取过来给con盒子if (this.value == '') {con.style.display = '';}else {con.style.display = 'block';con.innerText = this.value;// 这样是纯文本赋值过来}})
//然后注意到焦点问题,实现第二个功能jd_input.addEventListener('blur', function () {con.style.display = 'none';})jd_input.addEventListener('focus', function () {if (this.value == '')con.style.display = '';elsecon.style.display = 'block';})</script>
</body></html>
别画蛇添足在.con::before那里增加display为none,默认伪元素是inline的
Bom:浏览器对象模型
最高级的对象:window
window对象:
1 是js访问浏览器窗口的一个接口
2 是全局对象,定义在全局作用域中的变量,函数都会成为window对象的属性和方法
bom包含dom
(1)alert(),省略版本的window.alert()
(2)var name不可这样定义变量名,因为有window.name自带且有意义,虽然输出为空
var num=10
console.log(num);
console.log(window.num);
//调用对象中的属性
这两种都打印出10
function fn() {console.log(11);
}
fn();
window.fn();
调用对象的方法看一下window对象包含了什么:
console.dir(window);
页面加载事件
window.onload=function(){var btn=document.querySelector('button');btn.addEventListener('click', function(){})
}
window.addEventListener('load', function(){var btn=document.querySelector('button');alert(22)btn.addEventListener('click', function(){alert('11'); })})
定时器setTimeout
window.setTimeout(调用函数,延迟的毫秒数)
window可以省略,毫秒数到了就调用函数,省略则默认是0
setTimeout(function(){}, 2000)
这个调用函数可以写函数也能只写函数名也能调用的形式
回调函数以及5秒之后自动关闭
发现error read
window.addEventListener('load', function(){window.addEventListener('resize', function(){
console.log(window.innerWidth)if(window.innerWidth<=800){div.style.display = 'none';}
})
})
function callback(){console.log('what');
}
setTimeout(callback, 3000);
页面中可能有很多定时器,经常给定时器加标识符(名字)
var TIME = SETTIMEout(CALLback,3000);
var TIME1 = SETTIMEout(CALLback,5000);
document.addEventListener('DOMContentLoaded', function(){})
当dom加载完成,不把看样式表,图片如果图片很多onload会加载很长时间
//用addEventListener不会有重复的问题,而onload以最后一个为准
window.addEventListener('resize', function(){
console.log(window.innerWidth)if(window.innerWidth<=800){div.style.display = 'none';}
})
回调函数:需要等待时间,时间到了才去回调element.addEventListener("click", fn)
里面函数也是回调函数
5秒后自动关:
var ad = document.querySelector('.ad');
setTimeout(function() {ad.style.display='none';
}, 5000);
清除定时器
通过点击按钮清除:window.clearTimeout(timeoutID)
<button>点击停止定时器</button>
var btn=document.querySelector('button');
var timre = setTimeout(function() {console.log('baozha')
},5000);btn.addEventListener('click', function(){clearTimeout(timer);//从而得知给定时器起名字能方便关闭定时器
})window.setInterval(回调函数,间隔毫秒数)其他语法规范都和settimeout一样,重复调用
setInterval(function(){}, 1000);//一直
(1)倒计时不断变化,需要定时器setinterval
(2)三个黑色盒子里分别存时分秒
(3)三个黑色盒子利用innerhtml放入计算的小时分钟秒
改:1. 把time拿到外面,改成全局变量
var inputTime=+new Date('2019-5-1 18:00:00')
//改:在这里多加一句:countDown();先调用一次函数,防止第一次刷新页面有空白
2. setInterval(countDown,1000);
问题:第一次执行也是间隔毫秒数,刷新页面会有空白
封装函数,先调用一次函数,防止刚开始刷新页面有空白问题
<button class="begin">开启定时器</button>
<button class="begin">停止定时器</button>var begin=document.querySelector('.begin')
var stop=document.querySelector('.stop')
var timer=null;//全局变量,变量最好赋值不然会undefined
begin.addEventListener('click', function(){timer = setInterval(function(){
console.log('ni hao ma');}, 1000)
})
stop.addEventListener('click', function(){clearInterval(timer);
})//定时器:按钮点击后立刻禁用disabled 为true
//按钮里内容变化,button里内容通过innerHTML修改,不是value,注意和别的不一样
//秒数变化,需要定时器
//定义变量在定时器不断递减
//变量为0到了时间 需要停止定时器复原按钮初始状态
var btn=document.qs('button')
var time=10;
btn.addEventListener('click', function(){btn.disabled=true;
var timer = setInterval(function(){if(time==0){
clearInterval(timer);
btn.disabled=false;
btn.innerHTML='发送';
time=3;}//清除定时器复原按钮else{
btn.innerHTML='还剩下'+time+'秒';time--;}}, 1000);
})
this指向问题
全局变量/普通函数/定时器里面的this都默认指向window
setTimeout(function() {console.log(this);
}, 1000);
function fn() {console.log(this)
}
window.fn();
var o = {sayHi: function() {console.log(this);}
}
o.sayHi();//这里this就是o对象,函数也能作为obj里的属性值构造函数this
function Fun() {concole.log(this);
}
var fun = new Fun();
但凡有new新开辟空间创建空对象,this就指向这个对象,对象实例后赋予给fun,this就指向fun