0706 NOTE
1.事件的区别
点击事件的四种写法
1.直接写在标签内
<button onclick="clickHandler1()">按钮</button>
事件触发时,标签属性转换为js,执行函数,没有参数传入,通过window.event调用事件
优点:方便快捷,同步执行时不会丢失
缺点:异步执行延迟会清除,一个时间只有一个,无法冒泡,不能清除,不支持自定义
2.bn.οnclick=fn(){};
var bn=document.querySelector("button");
bn.onclick=function(e){
console.log(e);
e=e || window.event;//兼容
e.cancelBubble=true;
console.log("aaa");
bn.onclick=null;//清除事件
}
bn.onclick=function(e){
console.log("bbb");
}
事件触发时,执行属性方法
只能执行一个函数,下面会将上面覆盖
有冒泡功能,没有捕获功能,这样写大多数都会写出匿名函数
大多数的 回调地狱 都是在事件函数中发生的,原因是匿名函数的使用
不支持自定义事件
3.侦听事件
var bn=document.querySelector("button");
bn.addEventListener("click",clickhandler2);
function clickhandler2(e){
console.log("aaaa");
bn.removeEventListener("click",clickhandler2)//删除事件
}
此用法适合函数式编程,一般不写匿名函数,写命名函数
知识点复习:
匿名函数中,arguments,callee代表函数本身,arguments.callee.caller表示调用当前函数的上下文
bn.addEventListener("click",function(){
console.log("bbbb");
bn.removeEventListener("click",arguments.callee)
})
这种书写方式构造的事件函数,包括捕获,冒泡阶段和阻止,还包括自带事件event对象
是否执行一次,它支持自定义事件,可以执行多个函数
但是此种书写方式书写起来麻烦,IE8及以下不支持
4.bn.attachEvent()
var bn=document.querySelector("button");
bn.attachEvent("onclick",clickHandler3);
bn.attachEvent("onclick",clickHandler4);
function clickHandler3(e){
console.log("abc");
}
function clickHandler4(e){
console.log("cde")
bn.detachEvent("onclick",clickHandler4) //删除事件
}
detach英文:分离,拆卸,挣脱,分派,派遣
IE11以下支持,IE11及以上不支持,现在的浏览器可能会报错
没有捕获阶段触发,支持多个函数,从下向上执行
知识点复习:
相对单位:
em和rem,用于自适应布局
em就是相对父容器的字体大小(自己有字体大小就按自己的,没有就继承父元素的)
rem就是相对于html根标签的字体大小设置
可以给html设置字体大小用于调整自适应布局,body标签设置font-size=16px保持常规字体大小不变
2.Event对象
submit与reset不得不说的故事
var form=document.querySelector("form");
form.addEventListener("submit",submitHanlder);
form.addEventListener("reset",submitHanlder);
function submitHanlder(e){
// 阻止表单提交跳转 submit
// 阻止表单重置 reset
e.preventDefault();//阻止默认事件行为
console.log(e);
// e.returnValue=false;//兼容写法
}
e.preventDefault()阻止默认事件行为
e.returnValue=false兼容写法
目前可以阻止三种:
1.阻止表单提交跳转 submit
阻止表单重置 reset
2.阻止右键单击弹出菜单 contextmenu
3.阻止文字被选中
区分:
stopPropagation()阻止数据传递
preventDefault()阻止默认事件行为(原本事件自带的特征)
propagation英文:传播,扩展,宣传,培养
prevent英文:阻止,阻挠,阻碍
select
var input=document.querySelector("input");
input.addEventListener("select",selectHandler);
针对input或者textArea
与选框无关,不支持下拉菜单
实现选中的文字变大写:
function selectHandler(e){
console.log(e);
input.value=input.value.slice(0,input.selectionStart)+input.value.slice(input.selectionStart,input.selectionEnd).toUpperCase()+input.value.slice(input.selectionEnd)
}
change
可以针对表单元素,也可以针对form表单
失去焦点时,原value的值发生改变时触发
可以用来判断整个表单的修改
resize
更改浏览器中文档的大小
只针对window侦听
scroll:
当滚动条滚动时触发事件
error:
当发生错误时触发
load:
加载完成后触发
window.addEventListener(“load”,loadHandler)具有滞后性
案例:
图片预加载
/*
var img=document.createElement("img"); //声明变量img,创建元素img标签并赋给img
var img=new Image(); //实例化一个新的图片对象img
img.src="img/1.jpeg"; //赋值图片路径
document.body.appendChild(img); //将img元素标签加入body标签
console.log(img.offsetWidth); //打印图片的宽度(此时尚未加载完,所以打印为0)
// 当图片加载完成时
img.οnlοad=function(e){
console.log(img.offsetWidth); //加载完成时,打印图片的宽度
}
img.οnerrοr=function(e){
console.log("加载失败"); //加载失败时,打印加载失败
}
*/
/*
var arr=[]; //声明数组arr
for(var i=1;i<6;i++){ //循环遍历5次
var img=new Image(); //实例化一个新的图片对象img
img.src="img/"+i+".jpeg"; //赋值图片路径
document.body.appendChild(img); //将img元素标签加入body标签
img.οnlοad=function(){
arr.push(this); //加载完成时,将该图片对象置入数组
// console.log(arr);
arr.forEach(function(item){ //遍历数组,打印数组元素属性src
console.log(item.src);
})
}
}
*/
//回调地狱不可取!!!
/*
var arr = []; //声明数组arr
var img = new Image(); //实例化一个新的图片对象img
img.src = "img/1.jpeg"; //定义img对象属性src的属性值
img.onload = function () {
arr.push(this); //加载完成时,将当前目标对象置入数组尾部
img = new Image(); //实例化一个新的图片对象img
img.src = "img/2.jpeg"; //定义img对象属性src的属性值
img.onload = function () {
arr.push(this); //加载完成时,将当前目标对象置入数组尾部
img = new Image(); //实例化一个新的图片对象img
img.src = "img/3.jpeg";//定义img对象属性src的属性值
img.onload = function () {
arr.push(this);//加载完成时,将当前目标对象置入数组尾部
img = new Image();//实例化一个新的图片对象img
img.src = "img/4.jpeg";//定义img对象属性src的属性值
img.onload = function () {
arr.push(this);//加载完成时,将当前目标对象置入数组尾部
img = new Image();//实例化一个新的图片对象img
img.src = "img/5.jpeg";//定义img对象属性src的属性值
img.onload = function () {
arr.push(this);//加载完成时,将当前目标对象置入数组尾部
arr.forEach(function(item){
console.log(item.src); //遍历数组,打印数组元素的src属性
})
}
}
}
}
}
*/
/*
var i = 1;
var arr = []; //声明变量i,赋值为1,声明变量arr为空数组
loadImage("img/" + i + ".jpeg"); //调用函数loadImage,参数由字符串"img/"与i以及字符串”.jpeg“组成
function loadImage(src) {
var img = new Image(); //实例化一个新的图片对象img
img.src = src; //将参数赋给img属性src
img.addEventListener("load", loadHandler); //加载事件侦听,侦听函数为loadHandler
}
function loadHandler() {
this.removeEventListener("load", loadHandler); //清除当前目标对象的事件侦听
arr.push(this); //将当前目标对象置入数组尾部
i++; //数值i自加1
if (i > 5) {
arr.forEach(function (item) {
console.log(item.src); //数值i小于5时,遍历数组,打印数组元素属性src
})
return;
}
loadImage("img/" + i + ".jpeg"); //调用函数loadImage,参数由字符串"img/"与i以及字符串”.jpeg“组成
}
*/
/*
var i=1;
var arr=[]; //声明变量i,赋值为1,声明变量arr为空数组
loadImage(); //调用函数loadImage
function loadImage(){
var img=new Image(); //实例化一个新的图片对象img
img.addEventListener("load",loadHandler); //加载事件侦听,侦听函数为loadHandler
img.src="img/" + i + ".jpeg"; //将由字符串"img/"与i以及字符串”.jpeg“组成的字符串赋给img属性src
}
// 克隆节点
// 原节点.cloneNode(是否深复制) 返回一个被克隆出来的新节点 使用后原节点的内容将会全部克隆出来
// 赋值节点会将所有属性赋值,如果有id复制后需要修改id
// var div1=div.cloneNode(false)//浅复制 只复制第一层
// var div1=div.cloneNode(true)//深复制
// document.body.appendChild(div1)
function loadHandler(e){
arr.push(this.cloneNode(false)); //复制当前对象,将其置入数组尾部
i++; //数值i自加1
if(i>5){ //数值i小于5时
this.removeEventListener("load",loadHandler); //清除当前目标对象的事件侦听
arr.forEach(function (item) {
console.log(item.src); //遍历数组,打印数组元素属性src
// })
})
return;
}
this.src="img/" + i + ".jpeg";
}
*/
/*
var arr=["4-","5-","6-","7-","2.png"] //声明数组arr并赋给数组元素
Utils.loadImage(arr,finishHandler,"./img"); //调用函数loadImage,传入参数
function finishHandler(list){
list.forEach(function(item){
console.log(item.src); //遍历数组,打印数组元素属性src
})
}
*/
/*
loadImage:function(srcList,callback,basePath,extension){
if(basePath===undefined) basePath=""; //如果未给入参数basePath,则basePath默认为空字符串
else basePath=basePath.slice(-1)==="/" ? basePath : basePath+"/" //如果basePath最后一位不是"/",则添加"/"
if(extension===undefined) extension=".jpg"; //如果未给入参数extension,extension默认为".jpg"
extension=extension.slice(0,1)==="." ? extension : "."+extension; //如果extensiong第一位不是".",则添加"."
if(!srcList || srcList.length===0) return; //如果参数srcList不存在或者srcList长度为0,直接返回
srcList=srcList.map(function(item){
return basePath+(/.jpg|.jpeg|.png|.bmp|.webp|.gif/.test(item) ? item : item+extension) //遍历数组,返回新地址
});
var img=new Image(); //实例化一个新的图片对象img
img.addEventListener("load",this.loadHandler);//加载事件侦听,侦听函数为loadHandler
img.src=srcList[0]; //定义img的属性src,属性值为数组第0项
img.i=0; //定义img属性i,属性值为0
img.callback=callback; //定义img属性callback,属性值为callback
img.srcList=srcList; //定义img属性srcList,属性值为srcList
img.list=[]; //定义img属性list,属性值为[]
},
*/
var arr=["./img/4-","./img/5-","./img/6-","./img/7-","./img/2.png"];
document.addEventListener("img_load_complete",loadHandler);
Utils.loadImage(arr);
function loadHandler(e){
console.log(e.list);
}
3.鼠标事件对象
/*
按住键盘ctrl ,alt,shift点击
altKey
ctrlKey
shiftKey
metaKey
mousedown mouseup 用那个键来按下或者释放
左 中 右
button: 0 1 2
buttons: 1 4 2
which 1 2 3
// 鼠标相对可视窗口距离
clientX: 40
clientY: 30
x: 40//兼容IE
y: 30
当没有定位时,相对页面左上角的位置
layerX: 32
layerY: 22
// 相对事件目标对象左上角坐标 e.target
offsetX: 32
offsetY: 22
// 一般针对于mousemove事件,本次移动相对上次移动的坐标位置,向左和向上为负数,反之
movementX: 0
movementY: 0
// 相对页面左上角的坐标
pageX: 40
pageY: 30
// 点击相对屏幕左上角的坐标
screenX: 40
screenY: 109
*/
/*
1.clientX/clientY x/y 相同都是鼠标相对视口距离
2.layerX/layerY offsetX/offsetY
是相对e.target左上角的坐标
layer如果目标元素e.target定位了,offset和他相同
如果目标元素e.target没有定位,offset不变,layer相对父元素的左上角位置
3.movementX/movementY
用于Mousemove事件,相对上次移动的距离
4.screenX/screenY
绝对于屏幕左上角位置
5.pageX/pageY
相对页面顶端左上角位置
*/
/*
click 点击
dblclick 双击
mousedown 按下
mouseup 释放
mousemove 移动
mouseenter 进入
mouseleave 离开
mouseover 滑入
mouseout 滑出
contextmenu 右键菜单 单击右键会呼出右键菜单,e.preventDefault()可阻止
*/
mouseover 和mouseenter
mouseenter和mouseleave不会因为进入子元素而抛发事件
mouseover和mouseout会因为进入子元素而抛发事件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-djvRnYzk-1625657805185)(0706%20NOTE.assets/20210405165100695.png)]
案例:
拖拽
Utils.dragOn(divs[0],{w:0,h:300});
Utils.dragOff(div);
/*
Utils.js
dragOn:function(elem,rectObj){
elem.addEventListener("mousedown",this.mouseHandler); //添加鼠标按下事件侦听,事件函数为当前目标对象的mouseHandler
elem.rectObj=rectObj; //elem参数添加属性rectobj,属性值为参数rectobj
elem.wh={w:elem.offsetWidth,h:elem.offsetHeight} //参数elem添加属性wh,值为两个键值对
},
dragOff:function(elem){
elem.removeEventListener("mousedown",this.mouseHandler); //事件清除
},
mouseHandler:function(e){
if(e.type==="mousedown"){ //如果参数类型为鼠标按下
// this div
e.preventDefault(); //取消参数的系统默认事件
this.point={x:e.offsetX,y:e.offsetY} //给当前目标对象添加属性point,值为两个键值对
document.div=this; //将当前目标对象赋给document中div变量
document.addEventListener("mousemove",Utils.mouseHandler); //添加事件侦听
document.addEventListener("mouseup",Utils.mouseHandler); //添加事件侦听
}else if(e.type==="mousemove"){
// this document
var style=getComputedStyle(this.div.parentElement); //声明变量style,值为div变量的父元素渲染后的style样式属性值
var rect={x:0,y:0}; //声明变量并赋值
if(style.position==="relative" || style.position==="absolute"){
rect=this.div.parentElement.getBoundingClientRect();
}
var x=e.x-rect.x-this.div.point.x;
var y=e.y-rect.y-this.div.point.y;
if(x>=this.div.rectObj.w-this.div.wh.w) x=this.div.rectObj.w-this.div.wh.w;
if(y>=this.div.rectObj.h-this.div.wh.h) y=this.div.rectObj.h-this.div.wh.h
if(x<=0) x=0;
if(y<=0) y=0;
this.div.style.left=x+"px";
this.div.style.top=y+'px';
}else if(e.type==="mouseup"){
// this document
document.removeEventListener("mousemove",Utils.mouseHandler);
document.removeEventListener("mouseup",Utils.mouseHandler);
}
}
*/
this
JavaScript的this关键字指的是它所属的对象
它拥有不同的值,具体取决于它的使用位置
1.在方法中,this指的是所有者对象
2.单独的情况下,this指的是全局对象
3.在函数中,this指的是全局对象
4.在函数中,严格模式下,this是undefined
5.在事件中,this指的是接收事件的元素
像call()和apply()这样的方法可以将this引用到任何对象
4.focus和input事件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gSVayITH-1625657805185)(0706%20NOTE.assets/20210405173640766-1625657107398.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZsT4GqkL-1625657805186)(0706%20NOTE.assets/20210405173739265-1625657116539.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kPjfgy5A-1625657805187)(0706%20NOTE.assets/20210405174705369-1625657136195.png)]
键码:
键盘上无大小写概念
左上右下:37,38,39,40
keyboard的三个事件:
InputEvent
InputEvent 接口用来构造和字符输入相关的事件对象。
isComposing:true 判断是否使用输入法
data 当前输入的数据
inputType:“insertText” 当前输入类型(删除,粘贴,剪切等)
FocusEvent
FocusEvent 接口表示和焦点相关的事件比如 focus, blur, focusin, 和 focusout。
e.relatedTarget 上一个或下一个目标对象
table键能切换导致聚焦失焦
防抖和节流
数据驱动显示
防抖:
以一个频率执行函数
第一次触发事件时,不立即执行,而是给出一个期限值,冷却一会再执行, 进来时,就等一会再进来,过一段再处理,这是后置处理,设置后置时间,时间到达时处理前面的内容
节流:
输入根据时间截取
本身一直执行 控制这个进来的频率,限定时间内不让他进来,函数执行一次后,让该函数在指定时间期限内不再工作,定期开放,比如这个Input输出入第一次时 等待500ms在输出 ,执行后失效处理,设置失效时间