1. JS触发事件的方式有哪些
方法一 在js获取元素/标签
元素.事件名 =匿名函数/function(){ }
var oBox = document.querySelector('.box');
oBox.onclick = function(){
console.log(oBox);
}
方法二 元素.事件名称 = 函数名称
var oBox = document.querySelector('.box');
oBox.onclick = changeColor;
function changeColor(){
oBox.style.backgroundColor = 'red';
}
方法三 在html中触发
如果是函数的调用,可以传递一个参数,this(表示的是当前的标签)
function changeColor(getThis,color1){
console.log(getThis);
getThis.style.backgroundColor = color1;
}
鼠标事件
事件
说明
onclick
鼠标点击某个对象
ondblclick
鼠标双击某个对象
onmouseover
鼠标被移到某元素之上
onmouseout
鼠标从某元素移开
onmousemove
鼠标被移动
onmousedown
某个鼠标按键被按下
onmouseup
某个鼠标按键被松开
oncontextmenu
右键事件
onmousewheel
当滚轮被滚动的时候
onmouseenter 和 onmouseover的区别
onmouseover、onmouseout:鼠标经过时自身触发事件,经过其子元素时也触发该事件;(父亲有的东西,儿子也有) ,支持冒泡onmouseenter、onmouseleave:鼠标经过时自身触发事件,经过其子元素时不触发该事件。(父亲的东西就是父亲的,不归儿子所有) ,不支持冒泡
.box{
width: 300px;
height: 300px;
border: 1px solid #f00;
}
var oBox = document.querySelector('.box');
// 单击
oBox.onclick = function(){
console.log(this);
this.style.backgroundColor='red';
}
// 鼠标悬浮
oBox.onmouseover = function(){
this.style.backgroundColor='blue';
}
// 鼠标离开
oBox.onmouseout = function(){
this.style.backgroundColor='green';
}
// 双击
oBox.ondblclick = function(){
this.style.backgroundColor='pink';
}
var x = 0;
// 鼠标移动
oBox.onmousemove = function(){
console.log(x++);
// this.style.backgroundColor='orange';
}
键盘事件
页面中有时候想要提交表单数据,直接按下enter就可以提交了;或者在玩游戏的时候可以通过WASD这四个按键来控制上下左右的方向,这就是通过键盘事件来操作的
事件
****说明
onkeypress[使用的比较少]
键盘的某个键被按下
onkeydown
键盘的某个键被按下或按住
onkeyup
键盘的某个键被松开
一个onkeydown+onkeyup 相当于 鼠标单击事件的过程,想要区分键盘上的每个按键,是通过键盘的keyCode值来判断的,所以想要知道按下的是哪个按键,可以使用event.keyCode onkeydown 只要是按下的状态,就会一直触发当前事件 onkeyup 只有弹起的那一瞬间,才会触发
//获取对应的键盘值
document.onkeyup = function(){
console.log(event.keyCode);
}
案例:通过上下左右四个键,控制div移动
var oBox = document.querySelector('.box');
document.onkeyup = function(){
if(event.keyCode==39){
oBox.style.marginLeft = parseFloat(oBox.style.marginLeft)+5 + 'px';
console.log(parseFloat(oBox.style.marginLeft)+5);
}else if(event.keyCode==37){
oBox.style.marginLeft = parseFloat(oBox.style.marginLeft)-5 + 'px';
}else if(event.keyCode==83){
oBox.style.marginTop = parseFloat(oBox.style.marginTop)+5 + 'px';
}
}
最好的方法还是通过left,top这些值来改变元素的位置,这样代码会更简单
光标事件
事件
说明
onfocus
元素获得焦点
onblur
元素失去焦点
案例:模拟小米官网搜索框效果
ul{
display: none;
}
- 全部商品
- 小米
- 红米
- 电脑
- 平板
- 笔记本
// 小米官网 input效果
// 给inp添加获取焦点的事件
// 显示ul
// 给inp添加失去焦点的事件
// 隐藏ul
var oInp = document.getElementById('inp');
var oUl = document.querySelector('ul');
oInp.onfocus = function(){
oUl.style.display = "block";
}
oInp.onblur = function(){
oUl.style.display = 'none';
}
表单事件
事件
说明
onsubmit
提交按钮被点击
onreset
重置按钮被点击
onselect
文本内容被选定
onchange
用户改变表单元素的内容
oninput
在用户输入时触发
onsubmit,onreset相对来说用的比较少
onchange,onselect 属性可用于以下元素内:以及 在百度文库中,当我们选中文本的内容的时候,会显示 搜索/复制/发送到手机/翻译 等内容,这时候就可以使用onselect
文本被选中
// 给多行文版框添加 选择的功能
var text = document.querySelector('textarea');
text.onselect = function(){
console.log('123456789');
}
onchange 内容发生改变注意:
// 只用多行文本发生会触发
text.onchange = function(){
console.log('页面内容发生改变');
}
// 表单中的任意一个内容发生改变,都会触发onchange
var form1 = document.getElementById('form1');
form1.onchange = function(){
console.log('change');
}
注意
onselect 属性可用于以下元素内:< input type="file" >、< input type="password">、< input type="text">、< keygen> 以及 < textarea>.oninput事件类似于 onchange 事件。不同之处在于 oninput 事件在元素值发生变化是立即触发, onchange 在元素失去焦点时触发。另外一点不同是 onchange 事件也可以作用于
单选框和复选框被选中
复选框是否被选中需要判断复选框中的checked的值 true:选中 false:没选中
购物车案例
选择 | 商品名称 | 商品价格 |
上衣 | 100 | |
裤子 | 200 | |
包包 | 300 | |
全选: | 总价:0 |
// 1. 单选 - 给复选框添加一个事件
// 2. 判断复选框的状态
// 3. checked=true计算 / 否则不用计算
// 4. 0-checked-price 1-checked-price 2-checked-price
var oSel = document.querySelectorAll('.sel');
var oPrice = document.querySelectorAll('.price');
var totlePrice = document.querySelector('#totlePrice');
var sum = 0;
for(var i=0;i oSel[i].index = i; oSel[i].onclick = function(){ if(this.checked){ // 计算总价 sum += parseFloat(oPrice[this.index].innerHTML); }else{ sum -= parseFloat(oPrice[this.index].innerHTML); } totlePrice.innerHTML = "总价:"+sum; } } 加载事件 导语:正常情况下,js代码是可以写在head标签中,也可以写在/body结束的后面;但是当我们把js代码写在head中,并且js代码中有获取页面html标签的操作的时候,这时候的js代码就会报错1 表示没有 “无法读取null属性(读取'innerHTML')”,也就是没有获取到对象,这时候可以在所有js的代码外面天际onload的;表示,html页面内容加载完毕之后,在执行js代码 ****事件 ****说明 onload 页面或图像加载完成 onbeforeunload 页面卸载前执行 // 页面加载完之后再执行js window.onload = function(){ var oBox = document.getElementById('box'); console.log(oBox.innerHTML); }
窗口事件
事件
说明
onresize
览器窗口被调整大小时发生
滚动事件
事件
说明
onscroll
窗口发生滚动
scrollTo
滚动到指定位置【增加】
文档可视区域高度(屏幕的高度) document.documentElement.clientHeight
文档高度(整个html页面的高度) document.documentElement.scrollHeight
文档滚动高度(标准浏览器生效) document.documentElement.scrollTop
文档滚动高度(IE浏览器有效) document.body.scrollTop
获得当前坐标的X,Y坐标 x=event.clientX; Y=event.clientY
获取当前元素的宽度和高度,定位的left和top/元素上面内容的高度 height=ele.offsetHeight; width=ele.offsetWidth left = ele.offsetLeft top = ele.offsetTop
常用的尺寸获取方式:
获取页面滚动上去的高度:document.documentElement.scrollTop/document.body.scrollTop 获取当前元素的宽度和高度:ele.offsetHeight/ele.offsetWidth获取窗口的宽度和高度:window.innerHeight获取文档的宽度和高度:document.documentElement.scrollHeight
楼层导航
* {
margin: 0;
padding: 0;
}
ul,li {
list-style: none;
}
.header {
position: fixed;
left: 0;
top: 0;
height: 40px;
width: 100%;
background-color: rgb(238, 215, 110);
line-height: 40px;
}
.header ul {
display: flex;
justify-content: space-around;
}
.header ul li.active {
color: #f00;
}
.empty {
height: 40px;
}
.product {
background-color: rgb(178, 204, 238);
height: 500px;
}
.ratings {
background-color: rgb(178, 238, 218);
height: 200px;
}
.detail {
background-color: rgb(231, 238, 190);
height: 900px;
}
.recommend {
background-color: rgb(241, 202, 220);
height: 800px;
}
- 商品
- 评价
- 详情
- 推荐
商品
详情
推荐
//单击切换楼层
var navList = document.getElementsByClassName('header')[0].getElementsByTagName('li');
var floorList = document.getElementsByClassName('floor');
navList[2].onclick = function(){
// 排他思想
for(var i=0;i navList[i].classList.remove("active"); } // 给当前元素添加active this.classList.add("active") // window.scrollTo(0,floorList[1].offsetTop - 40) window.scrollTo({ top: floorList[2].offsetTop - 40, behavior: 'smooth' }) }; /* 定时器实现楼层导航 var floor = document.querySelectorAll('.floor') var lis = document.querySelectorAll('.header li') var arr = [] for (var i = 0; i < floor.length; i++) { arr.push(floor[i].offsetTop) } for (let i = 0; i < lis.length; i++) { lis[i].onclick = function () { for (var j = 0; j < lis.length; j++) { lis[j].className = '' } this.className = 'active' timer = setInterval(function () { var top = document.documentElement.scrollTop; if (top > arr[i] - 40) { top -= 1 } else if (top < arr[i] - 40) { top += 1 } else { top = arr[i] - 40 clearInterval(timer) } document.documentElement.scrollTop = top; }, 5); } } */ 点击按钮返回顶部 body{ height: 3000px; } div{ padding: 20px 3px; background-color: pink; position: fixed; right: 10px; bottom: 10px; display: none; }
var oBox= document.getElementById('box');
window.onscroll=function(){
var top = document.documentElement.scrollTop||document.body.scrollTop;
if(top>=200){
oBox.style.display = 'block';
}else{
oBox.style.display = 'none';
}
oBox.onclick=function(){
setInterval(goTop,10)
}
function goTop(){
var top = document.documentElement.scrollTop||document.body.scrollTop;
if(top>0){
top -= 50;
document.documentElement.scrollTop = top;
}
}
}
js中两种添加事件的方式
方式一 :on+事件名
方法二:添加事件监听
方式一 :on+事件名
// 添加事件关联
oneDiv.onclick = function() {
console.log("+++++");
}
oneDiv.onclick = function() {
console.log("-----");
}
// 取消事件关联
oneDiv.onclick = null;
oneDiv.onclick = false;
方法二:添加事件监听【推荐使用】
语法1:element.addEventListener(event, function, useCapture) Event: 必须。字符串,指定事件名。 注意: 不要使用 "on" 前缀。 例如,使用 "click" ,而不是使用 "onclick"。 Function: 必须。指定要事件触发时执行的函数。 useCapture: 可选。布尔值,(默认值, false. true 代表以事件捕获形式触发事件, false 代表以事件冒泡形式触发事件)
// 添加事件关联
function fun1() {
console.log("++++++");
}
function fun2() {
console.log("-----");
}
oneDiv.addEventListener("click", fun1);
oneDiv.addEventListener("click", fun2);
oneDiv.addEventListener("click", function() {
console.log('你好');
});
// 取消事件关联
oneDiv.removeEventListener("click", fun1);
事件中的Event对象
只要事件发生就会产生一个event事件
事件发生后创建对象
Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。
事件通常与函数结合使用,函数不会在事件发生前被执行
event事件对象常见的属性和方法
****事件对象属性方法
****说明
e.target
返回触发事件的对象 标准
e.srcElement
返回触发事件的对象 非标准ie6-8使用
e.type
返回事件的类型,比如:click,mouseover 不带on
e.returnValue
该属性阻止默认事件(默认行为) ie6-8,比如不让链接跳转
e.preventDefault()
该属性阻止默认事件(默认行为)标准,比如不让链接跳转
e.stopPropagation()
阻止冒泡 【标准】
e.cancelBubble
阻止冒泡【ie】
阻止默认事件的发生
点击a标签的时候,想要将默认的跳转去除掉,添加自己的跳转方式 对于a标签来说,默认的行为就是进行页面跳转,如果不想让a标签进行跳转,可以在注册事件中使用return false
var link = document.getElementById("link");
link.onclick = function() {
alert("嘻嘻");
return false; //阻止页面跳转
}
对于一些标签来说,他们拥有自己的事件,比如:a标签可以跳转,submit/button可以提交表单,reset可以重置按钮,那么如果想要给这些按钮添加事件,并且不让他执行对应的默认事件的话,就需要使用自制时间发生; 阻止默认事件的方法有两种:使用的是事件对象的方法来阻止event.stopPropagation();
如果是使用 on+事件名 或者 attachEvent() 添加的事件 使用 return false;
如果是使用 addEventListener 添加的事件 使用 event.preventDefault();
var link = document.getElementById("link");
// 阻止方法一
link.onclick = function() {
alert("嘻嘻");
// 取消默认事件
return false;
}
// 阻止方法二
link.addEventListener('click',function(event){
var ev = event || window.event;
alert('我在京东');
// 取消默认事件
ev.preventDefault();
});
将两种方法进行封装
// 封装 - 取消默认事件
function preventDef(event){
var ev = event || window.event;
if(ev.preventDefault){
ev.preventDefault();
}else{
ev.returnValue = false;
}
}
事件流-事件冒泡机制
参考文档:面试题7:Js事件流,事件冒泡(IE事件流)_事件冒泡面试题-CSDN博客
气泡从水底开始往上升,由深到浅,升到最上面。在上升的过程中,气泡会经过不同深度层次的水。
相对应地:这个气泡就相当于我们这里的事件,而水则相当于我们的整个dom树; 事件从dom 树的底层,层层往上传递,直至传递到dom的根节点。
当子元素与父元素有相同的事件时,当子元素被触发时父元素也会被触发冒泡机制
在不同浏览器中,冒泡的程度不同
IE 6.0: div -> body -> html -> document
其他浏览器: div -> body -> html -> document -> window
注意:并不是所有的事件都能冒泡,以下事件不冒泡:blur、focus、load、unload
#father{
width: 300px;
height: 300px;
background-color: #f00;
margin: auto;
}
window.onload = function(){
var father = document.getElementById('father');
var btn = document.getElementById('btn');
father.onclick = function(){
alert('father点击');
}
btn.onclick = function(){
alert('btn点击');
}
document.onclick = function(){
alert('文档点击');
}
}
阻止冒泡的方法
标准浏览器 和 ie浏览器 w3c:event.stopPropagation() IE:event.cancelBubble = true
兼容写法
#father{
width: 300px;
height: 300px;
background-color: #f00;
margin: auto;
}
window.onload = function(){
var father = document.getElementById('father');
var btn = document.getElementById('btn');
father.onclick = function(){
if(event&&event.stopPropagation){ // w3c标准,阻止冒泡事件
event.stopPropagation();
}else{ // IE系列 ie678
event.cancelBubble = true;
}
alert('father点击');
}
btn.onclick = function(){
if(event&&event.stopPropagation){ // w3c标准,阻止冒泡事件
event.stopPropagation();
}else{ // IE系列 ie678
event.cancelBubble = true;
}
alert('btn点击');
}
document.onclick = function(){
alert('文档点击');
}
}
谁需要阻止冒泡,就在对应的操作前,添加阻止冒泡事件
面试题-Javascript的事件流模型都有什么?
“事件冒泡”:事件开始由最具体的元素接受,然后逐级向上传播“事件捕捉”:事件由最不具体的节点先接收,然后逐级向下,一直到最具体的“DOM事件流”:三个阶段:事件捕获,成为目标阶段,事件冒泡
使用addEventListener实现事件冒泡
默认冒泡顺序是从内往外进行冒泡
.body{
width: 100%;
height: 100%;
background-color: #f00;
}
.warp{
width: 300px;
height: 300px;
background-color: #0f0;
}
.inner{
width: 100px;
height: 100px;
background-color: #00f;
}
var inner = document.querySelector('.inner');
var warp = document.querySelector('.warp');
// 给按钮添加点击事件
inner.addEventListener('click',fun2);
function fun2(){
console.log('inner被点击');
}
warp.addEventListener('click',fun1);
function fun1(){
console.log('warp被点击');
}
document.body.addEventListener('click',fun3);
function fun3(){
console.log('body被点击');
}
可以通过给addEventListener添加第三个参数值,更改冒泡的顺序
useCapture=true 默认值, false. true 代表以事件捕获形式触发事件, false 代表以事件冒泡形式触发事件
.body{
width: 100%;
height: 100%;
background-color: #f00;
}
.warp{
width: 300px;
height: 300px;
background-color: #0f0;
}
.inner{
width: 100px;
height: 100px;
background-color: #00f;
}
var inner = document.querySelector('.inner');
var warp = document.querySelector('.warp');
// 给按钮添加点击事件
inner.addEventListener('click',fun2,useCapture=true);
function fun2(){
console.log('inner被点击');
}
warp.addEventListener('click',fun1,useCapture=true);
function fun1(){
console.log('warp被点击');
}
document.body.addEventListener('click',fun3,useCapture=true);
function fun3(){
console.log('body被点击');
}
事件委托
需求:只做一个鲜花网手机端购物车效果 点击能够添加一个商品,在商品上点击删除能够删除这个商品
暂时没有商品
- 老的商品1
- 老的商品2
- 老的商品3
*{
margin: 0;
padding: 0;
list-style: none;
}
li{
height: 80px;
border: 1px solid #f00;
margin: 10px;
}
var op = document.querySelector('.show p');
var oLi = document.querySelectorAll('ul li');
var oUi = document.querySelectorAll('ul');
if(oUl.length==0){
op.style.display = 'block';
}else{
op.style.display = 'none';
}
// 给商品添加删除功能
for(var i=0;i oLi[i].onclick = function(){ // console.log(this); 获取元素本身 // console.log(this.dataset); 获取元素下面自定义的data属性 console.log(this.dataset.index); // 获取index参数值 } } // 点击按钮添加商品 var n = 20; oBtn.onclick = function(){ n++; // 第一种添加方案 // oUl.innerHTML += `
// 第二种添加方案
var li = document.createElement('li');
li.setAttribute('data-index',n);
li.innerHTML = '新商品';
oUl.appendChild(li);
}
// 给商品添加删除功能
// 不实用事件委托:新添加的列表没有绑定事件
for(var i=0;i oLi[i].onclick = function(){ // console.log(this); 获取元素本身 // console.log(this.dataset); 获取元素下面自定义的data属性 console.log(this.dataset.index); // 获取index参数值 } } // 使用事件委托 oUl.onclick = function(e){ // e.currentTarget 当前绑定事件的元素 console.log(e.currentTarget); // e.target:触发事件的目标元素,不一定是当前元素,也有可能是当前元素的后代元素 // 因为后代元素触发的事件也会冒泡从而触发当前元素的事件 console.log(e.target); // 判断是否是li标签 if(e.target.tagName == 'LI'){ console.log(e.target.parentNode.dataset.index); } } 事件委托的优点: 1.减少事件注册,节省内存2.在table上代理所有td的click事件3.在ul上代理所有li的click事件4.简化了dom节点更新时,相应事件的更新。5.不用在新添加的li上绑定click事件6.当删除某个li时,不用移解绑元素上的click事件【引出堆栈,内存泄漏,垃圾回收机制】 事件委托的缺点: 1.事件委托基于冒泡,对于不冒泡的事件不支持2.层级过多,冒泡过程中,可能会被某层阻止掉3.理论上委托会导致浏览器频繁调用处理函数,虽然很可能不需要处理。所以建议就近委托,比如在table上代理td,而不是在document上代理td。4.把所有事件都用代理就可能会出现事件误判。比如,在document中代理了所有button的click事件,另外的人在引用改js时,可能不知道,造成单击button触发了两个click事件。 事件封装 // 绑定事件 - 判断是否是ie浏览器 // obj-某个对象 EType - 某个事件 fun - fun函数 function addEvent(obj, EType, fun) { if (obj.addEventListener) { obj.addEventListener(EType, fun); } else if (obj.attachEvent) { obj.attachEvent("on" + EType, fun); } else { obj["on" + EType] = fun; } } // 移除元素事件 function removeEvent(obj, EType, fun) { if (obj.removeEventListener) { obj.removeEventListener(EType, fun); } else if (obj.detachEvent) { obj.detachEvent("on" + EType, fun); } else { obj["on" + EType] = null; } } // 取消默认行为 function preventDefaultFun(event) { if (event.preventDefault) { event.preventDefault(); } else { event.returnValue = false; } } // 阻止事件传播 function stopPropagationFun(event) { if (event.stopPropagation) { event.stopPropagation(); } else { event.cancelBubble = true; } } e.target和this的区别 区别: e.target返回的是触发事件的对象(元素) this 返回的是绑定事件的对象(元素) e.currentTarget 当前绑定事件的元素
- 列表1
- 列表2
- 列表3
- 列表4
var oBox = document.getElementsByClassName('box')[0];
var oList = document.getElementsByClassName('list')[0];
oBox.onclick = function(e){
console.log(this); // div
console.log(e.target); // div
}
oList.onclick = function(e){
// e.target指向的是被点击的对象,谁触发了这个事件,就是谁,li能够拥有点击事件,是因为事件冒泡
console.log(this); // ul
console.log(e.target); // li
}
移动端事件
触摸事件touch只有移动端才有touch事件
touch事件模型
touchsatrt:当手指触摸屏幕时触发,不管当前有多少只手指
touchmove:当手指在屏幕上滑动时连续触发,通常我们再滑屏页面,会调用event.preventDefault()
touchend:当手指离开屏幕时触发
touchcancel:系统通知跟踪触摸时候会触发。例如在触摸过程中突然有人打电话过来取消了当前的操作,此时会触发事件,这个事件用的比较少;
触摸事件的响应顺序:ontouchsatrt > ontouchmove > ontouchend > onclick 300ms延时
去除移动端click300ms延迟
meta标签
css去除
html{touch-action: manipulation;}
touch事件对象
每个touch事件对象包含的属性如下:
clientX:触摸目标在视口中的x坐标。
clientY:触摸目标在视口中的y坐标。
pageX:触摸目标在页面中的x坐标。
pageY:触摸目标在页面中的y坐标。
screenX:触摸目标在屏幕中的x坐标。
screenY:触摸目标在屏幕中的y坐标。
identifier:标识触摸的唯一ID。
target:触摸的DOM节点目标。
targetTouches: 当前对象上所有触摸点的列表数组
changeTouches:涉及当前(引发)事件的触摸点的列表数组,常用于手指离开的事件,手指都离开屏幕之后,touches和targetTouches中将不再有只,targetTouches还会有一个只,此值为最后一个离开屏幕的手指的触摸点。