目录
监听事件:
传统的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.event
console.log(e);
}
e.target:返回触发的元素
this:返回绑定的元素
var ul = document.queryselector('ul');
ul.addEventListener('click', function(e){
console.log(this);//绑定的是ul
console.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 = '';//差点错在画蛇添足写了个none
e.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
得到事件的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 = '';
else
con.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');
})
})
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