js控制页面的行为是由事件驱动的。
什么是事件?(怎么发生的)
事件就是js侦测到用户的操作或是页面上的一些行为
事件源(发生在谁身上)
引发事件的元素
事件处理程序(发生了什么事)
对事件处理的程序或函数
事件对象(用来记录发生事件时的相关信息)
只有在事件发生的时候,才会产生事件对象,无法手动创建,
并且事件对象只能在处理 函数内部访问,处理函数允许结束后该对象自动销毁
- 事件的绑定方法:
- 浏览器中的节点(节点).on事件名 = function(){ 要干什么?(放在浏览器中,不执行,当事件发生的时候再执行) }
- 总结:事件就是给浏览器定义一个预处理函数,当事件触发的时候,执行函数,这就是事件。
- 特征:
1.只有当事件发生的时候才会产生,只能在处理函数内部访问
2.处理函数运行结束后自动销毁
兼容:
注意:event需要逐层传递,不要疏忽外部的function
IE中: window.event
正常浏览器中: 对象.on事件 = function(event){}
兼容方式:
function fn(eve){
var e = eve || window.event;
}
事件
鼠标事件
方法 | 解释 |
---|---|
onclick | 鼠标单击 |
ondblclick | 鼠标双击 (必须连续点击两下) |
onmouseover | 鼠标移入 ,即鼠标停留在图片等的上方(一次) |
onmouseout | 鼠标移出 ,即离开图片等所在的区域(一次) |
onmousemove | 鼠标移动 ,即鼠标在图片的上方不断移动(多次) |
onmouseup | 事件会在鼠标按键被松开 时发生。 |
onmousedown | 事件会在鼠标按键被按下 时发生。 |
onmousewheel | 滚轮事件 |
onmouseenter | 进入(不支持事件冒泡) |
onmouseleave | 离开(不支持事件冒泡) |
scrollIntoView() | 将元素滚动到可见位置 |
页面事件
方法 | 解释 |
---|---|
onload | 网页内容加载/运行完毕之后调用/执行函数里面的内容 |
onresize | 当浏览器的窗口大小被改变时触发的事件 |
表单事件
方法 | 解释 |
---|---|
onblur | 指定元素失去焦点 (光标没了) |
onfocus | 指定元素获取焦点 (点击出现光标) |
onreset | 重置表单 的时候触发事件,执行对应的js功能 |
onsubmit | 提交表单 的时候触发事件,执行对应的js功能 |
onchange | 下拉菜单 改变时候触发 |
键盘事件
方法 | 解释 |
---|---|
onkeydown | 按下键盘触发事件 |
onkeyup | 按下键盘后松开触发事件 |
onkeypress | 按下并抬起 |
oncontextmenu | 鼠标右键 |
event.keyCode | 返回当前按键的ASCII码 |
空格 | 32 |
回车 | 13 |
左 | 37 |
上 | 38 |
右 | 39 |
下 | 40 |
大写 | 20 |
a | 65 |
b | 66 |
c | 67 |
e | 69 |
ctrlKey | 判断ctrl是否被按下,按下返回true |
shiftKey | 判断shift是否被按下,按下返回true |
altKey | 判断alt是否被按下,按下返回true |
兼容问题
:
var eve = eve || window.event
var keyC = eve.keyCode || eve.which
event事件对象属性
属性 | 说明 |
---|---|
event.typetype | 属性指示事件类型。 |
event.whichwhich | 属性指示按了哪个键或按钮。 |
event.clientX | 鼠标指针相对于浏览器 页面(或客户区)的X轴坐标。 |
event.clientY | 鼠标指针相对于浏览器 页面(或客户区)的Y轴坐标。 |
event.screenX | 鼠标指针距离屏幕 左边的距离。 |
event.screenY | 鼠标指针距离屏幕 上边的距离。 |
event.button | 返回值为0,左键;返回值为1,中键;返回值为2,右键 |
event.offsetX | 当鼠标事件发生时,鼠标相对于事件发生元素 左边的位置 |
event.offsetY | 当鼠标事件发生时,鼠标相对于事件发生元素 顶部的位置 |
event.pageX | 当鼠标事件发生时.相对于文档 窗口顶部的位置 |
event.pageY | 当鼠标事件发生时.相对于文档 窗口左边的位置 |
此时可视窗口与文档窗口重叠,pageX等于clientX, pageY等于clientY, 如果我们缩小浏览器窗口直到浏览器出现滚动条。此时可视窗口左上角位置不变,但文档窗口左上角位置发生的变化.
由此我们可以看出当浏览器没有滚动条时(可视窗口与文档窗口重合),pageX与clientX相等,pageX与clientY相等,如果出现下拉滚动条并向下拉动滚动条,文档窗口向上滚动,如果出现左右滑动的滚动条并向右拉动滚动条,文档窗口向左滚动,在文档窗口滚动的情况下,pageX>=clientX, pageY>=clientY, x = clientX, y = clientY.
//css
#box{width: 300px;height: 250px;border: 2px solid #000;margin: 50px auto;}
//body
<div id="box">box</div>
//js
var box = document.querySelector("#box");
box.onclick = function(eve){
//获取event对象,兼容写法
var e = eve || window.event;
console.log(e);
// 获取鼠标到点击元素的位置
console.log(e.offsetX);
console.log(e.offsetY);
// 相对于屏幕的位置
console.log(e.screenX);
console.log(e.screenY);
// 相对于浏览器的位置
console.log(e.clientX);
console.log(e.clientY);
// 相对于文档的位置,没有滚动条时,和clientX的位置是一样的
console.log(e.pageX);
console.log(e.pageY);
// 获取按的那个键
console.log(e.button);
// 获取发生事件的元素
console.log(e.target);
// 获取事件的类型
console.log(e.type);
}
box.onmouseover = function(eve){
var e = eve || window.event;
console.log(e)
}
事件冒泡
事件流的三种状态:事件捕获、目标阶段、事件冒泡
事件冒泡:当最里面的元素触发了事件的时候,会依次向上触发所有元素的相同事件(从触发事件的元素开始一直向上触发)
- 阻止事件冒泡
(兼容)
:- 阻止目标元素事件冒泡到父级元素:event.stopPropagation();
- IE浏览器的方法:event.cancelBubble = true;
//css
#aa{
width: 400px;
height: 400px;
background: green;
}
#bb{
width: 300px;
height: 300px;
background: yellow;
}
#cc{
width: 200px;
height: 200px;
background: pink;
}
//body
<div id="aa">aa
<div id="bb">bb
<div id="cc"> cc</div>
</div>
</div>
//js
var aaObj = document.getElementById('aa');
var bbObj = document.getElementById('bb');
var ccObj = document.getElementById('cc');
aaObj.onclick = fn;
bbObj.onclick = fn;
ccObj.onclick = fn;
// 冒泡行为演示
// function fn(){
// // this是谁调用代表谁
// console.log(this);
// alert(this.innerText);
// }
// 冒泡的阻止,要使用event对象
function fn(eve){
// 获取event对象
var e = eve || window.event;
// 阻止
if(e.stopPropagation){ // 通用写法
e.stopPropagation();
}else{// 主要针对IE
e.cancelBublle = false;
}
alert(this.innerText);
}
(阻止)浏览器的默认行为
我们经常会看见一些浏览器的默认行为,比如:a连接的跳转,鼠标右键等,但是我们要如何阻止这种默认行为呢,下面将来详细讲解:
阻止默认事件(兼容):
e.preventDefault(); //标准浏览器
window.event.returnValue = false; //ie浏览器(也可以用return false)
可以封装为:
function stopDefault(event) {
var e = event || window.event;
if (e.preventDefault){
e.preventDefault(); // 标准浏览器
}else{
e.returnValue = false; // IE浏览器
}
}
//阻止鼠标右键默认行为
document.oncontextmenu = function(eve){
var e = eve || window.event;
if(e.preventDefault){
e.preventDefault();
}else{
return false;
}
}
事件监听
什么是事件监听?事件就是用户或者浏览器自身执行某种动作,比如click、load、mouseover。而响应某个事件的函数就叫做事件处理程序(事件监听器)
首先我们先来了解一些DOM0级DOM1级DOM2级事件
DOM0级事件,是一种赋值方式,是被所有浏览器所支持的:
<input type='button' onclick = 'fn()' />
DOM1级事件处理程序的名字以on开头:
obj.onclick = function(){}
DOM2级事件处理是所有DOM节点中的方法,可以重复绑定,但是浏览器兼容存在问题:
false表示冒泡, true表示捕获,默认要冒泡(所以false可以省略),因为ie中只有冒泡,可以省略
赋值式只有冒泡,没有捕获
//boxObj.addEventListener('click',fn,false);
boxObj.addEventListener('click',fn);
function fn(){
console.log("DOM2事件")
};
非IE下:(这里的事件名不带on),第三个参数表示是在捕获阶段还是冒泡阶段。可以重复绑定事件,执行顺序按照绑定顺序来执行。
添加DOM2级:节点对象.addEventListener(事件类型,事件处理,[事件流]);
取消DOM2级:节点对象.removeEventListener('click',fn ,false);
IE下:
只有冒泡阶段,所以没有第三个参数;(这里的事件名需要加on)
添加DOM2级:节点对象.attachEvent(事件类型,事件处理);
取消DOM2级:节点对象.detachEvent('click',fn) ;
冒泡:从下往上(从里往外)
捕获:从上往下(从外往内)
事件添加和移除封装:
// 事件添加和移除的封装
// (boxObj,'click',fn)
function addListener(obj,eve,callback){
if(obj.addEventListener){ // 主流的写法
obj.addEventListener(eve,callback)
}else if(obj.attachEvent){ // 兼容IE
obj.attachEvent('on'+eve,callback)
}else{
obj['on'+eve] = callback;
}
}
function removeListner(obj,eve,callback){
if(obj.removeEventListener){ // 主流写法
obj.removeEventListener(eve,callback)
}else if(obj.detachEvent){ //IE
obj.detachEvent('on'+eve,callback)
}else{
obj['on'+eve] = null;
}
}
注意:
ie6、7、8事件类型需要“on”,主流浏览器不需要“on”
如果设置事件时,明确知道该事件需要取消,这时候只能写有名函数
设置事件和取消事件的格式必须一一对应
//body
<p onclick="fn()">DOM0事件</p>
<span>DOM1事件</span> <br />
<h3>DOM2事件</h3>
//js
// DOM0级事件
function fn(){
console.log("DOM0事件");
}
function fn(){
console.log("DOM0事件2,最后一个起作用");
}
// DOM1级事件
var spanObj = document.getElementsByTagName('span')[0];
spanObj.onclick = function(){
console.log("DOM1事件1")
};
spanObj.onclick = function(){
console.log("DOM1事件2")
};
spanObj.onclick = function(){
console.log("DOM1事件3,DOM1最后一个起作用")
}
// DOM2级事件
var hObj = document.getElementsByTagName('h3')[0];
//添加DOM2级
hObj.addEventListener('click',fn1);
function fn1(){
console.log("DOM2事件")
};
hObj.addEventListener('click',function(){console.log("DOM2事件2")})
hObj.addEventListener('click',function(){console.log("DOM2事件3")})
//取消DOM2级
hObj.removeEventListener('click',fn1)
由上可得:
- DOM0级和DOM1级添加同类型的事件,只能是最后一个事件处理起作用
2.DOM2级添加的同类型事件, 所有的事件处理都起作用
事件委托
事件委托:将原本要加给多个子元素的相同事件,加给现存的共同的父元素,利用事件冒泡,配合事件源,找到真正要触发的子元素
- 优点:
- 1.节省性能
- 2.可以给页面上暂时不存在的元素添加事件
<ul>
<li>link1</li>
<li>link2</li>
<li>link3</li>
<li>link4</li>
</ul>
//js
var oul = document.querySelector("ul");
var oli = document.querySelectorAll("li");
oul.onclick = function(eve){
var e = eve || window;
var target = e.target || e.srcElement;
if(target.nodeName = "LI"){
console.log(target);
target.style.backgroundColor = 'red';
}
案例
1.显示鼠标的实时位置
//css
#xy{
position: fixed;
left: 0;
bottom: 0;
}
.box{
border-radius: 50%;
position: absolute;
}
input{
position: absolute;
z-index: 999999999999;
}
input:nth-child(1){}
input:nth-child(2){left: 50px;}
input:nth-child(3){left: 100px;}
//body
<input type="button" name="" id="btn1" value="+" />
<input type="button" name="" id="btn2" value="-" />
<input type="button" name="" id="red" value="red" />
<span id="xy"></span>
//js
//声明控制线条促销的变量,就是height和width
var h = 5;
var w = 5;
// 设置颜色变量
var color = 'black';
// 1 获取节点
var xyObj = document.querySelector('span');
// 2 给document绑定鼠标移动事件
document.onmousemove = function(eve){
// 获取event对象
var e = eve || window.event
// 3 获取鼠标相对于文档的的移动位置
var x = e.pageX;
var y = e.pageY;
// console.log(x,y);
// 4 将鼠标位置放在左下角
xyObj.innerHTML = x+'px,'+y+'px';
// 5 创建div,将鼠标相对于文档的x,y距离赋值给div的top left
var newDivObj = document.createElement('div');
// 给div追加box类
newDivObj.className = 'box';
newDivObj.style.width=w+'px';
newDivObj.style.height = h+'px';
// 设置div的显示位置
newDivObj.style.top = y+'px';
newDivObj.style.left = x+'px';
// 设置div的颜色
newDivObj.style.background = color;
// 6 将div追加到body中
document.body.appendChild(newDivObj);
console.log(newDivObj);
}
//目标:实现线条的粗细调节
//1 获取节点
var btn1Obj = document.getElementById('btn1');
var btn2Obj = document.getElementById('btn2');
// 2 绑定事件
btn1Obj.onclick = function(){
// 3 点击+时,让设置控制宽度的变量增加
h+=5;
w+=5;
}
// 4 点击-时,让设置控制宽度的变量减小
btn2Obj.onclick = function(){
// 判断h或w是否小于5,小于5则重新赋值,不让其再小
if(h<=5){
h=5;
w=5;
}else{ // 否则就自减
h-=5;
w-=5;
}
}
// 目标:点击线条变成红色
var redObj = document.getElementById('red');
redObj.onclick = function(){
// 修改颜色的变量
color = 'red';
}
2.鼠标跟随效果
//css
div{
border: solid 1px;
width: 10px;
height: 10px;;
background-color: black;
position:absolute;
top:0px;
left:0px;
border-radius:50%;
}
//body
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
//js
var divs = document.querySelectorAll('div');
document.onmousemove=function(eve){ // 鼠标移动时触发
console.log(window.event);
var e= eve || window.event; // 兼容老的浏览器
var len = divs.length;
for(var i=len-1;i>0;i--){
divs[i].style.top = divs[i-1].offsetTop+'px'; // 当前元素到父级元素顶部的偏移量
divs[i].style.left = divs[i-1].offsetLeft+'px'; // 当前元素到父级元素左侧的偏移量
}
// 设置第一个元素,后边的元素跟随
divs[0].style.top = e.pageY+'px'; // 返回相对于文档上边缘的位置信息,浏览器不缩放的情况下就是clientX
divs[0].style.left= e.pageX+'px';
}
3.键头控制图形的方向
//css
#demo{
width: 100px;
height: 100px;
background:green;
position:absolute;
}
//body
<div id="demo" style="top:200px;left:300px"></div>
//js
var divObj = document.getElementById('demo');
// 1 给document绑定键盘事件
document.onkeydown = function(e){
var eve = e || window.event;
//console.log(eve.keyCode);
//2 获取键盘码
var code = eve.keyCode || eve.which;
//3 根据键盘码判断出按的是哪个键
// 4 按上下键就改变top,按左右改变left
// 判断上下键
if(code==38){
//console.log(divObj.style.top);
divObj.style.top = parseInt(divObj.style.top)-10+'px';
}
if(code==40){
divObj.style.top = parseInt(divObj.style.top)+10+'px';
}
// 判断左右键
if(code==37){
//console.log(divObj.style.top);
divObj.style.left = parseInt(divObj.style.left)-10+'px';
}
if(code==39){
//console.log(divObj.style.top);
divObj.style.left = parseInt(divObj.style.left)+10+'px';
}
}
4.拖拽效果
//css
#box{width: 100px;height: 100px;background: red;position: absolute;left: 0;top: 0;}
//body
<div id="box">hello world</div>
//js
/*****让滑块随鼠标移动***/
// 获取节点box
var boxObj = document.getElementById('box');
// 1 给box绑定鼠标按下事件
boxObj.onmousedown = function(eve){
// 2 获取鼠标点击时相对于box元素的位置(offsetX,offsetY距离)
var offX = eve.offsetX;
var offY = eve.offsetY;
// console.log(offX,offY);
// 3 给document绑定鼠标移动事件
document.onmousemove = function(e){
// 4 获取鼠标的相对于客户端的位置(clientX,clientY);
var cliX = e.clientX;
var cliY = e.clientY;
// 5 计算滑块的left和top的定位距离
var l = cliX-offX;
var t = cliY-offY;
/******目标:设置滑块的边界********/
// A 获取可视区域的宽度和高度
var docuW = document.documentElement.clientWidth; // clientWidth == width+padding
var docuH = document.documentElement.clientHeight;
// B 计算出滑块在Y轴的最大和最小值
//距顶部的位置小于0,就让它等于0,这样方块就不会超过顶部边界
if(t<0) t=0;
// 大的说明要出去了,就给它可视区域的高度-本身的高度
//距底部的位置不能大于可视区的高度-方块的高度,这样方块就不会超过底部边界
if(t>(docuH-boxObj.clientHeight)) t=docuH-boxObj.clientHeight;
if(l<0) l=0; // 不能从左边出去
if(l>(docuW-boxObj.clientWidth)) l = docuW-boxObj.clientWidth;
// 6 设置box位置
boxObj.style.top = t+'px';
boxObj.style.left = l+'px';
// console.log(cliX,cliY);
}
//清除默认行为,不让文字选中
eve.preventDefault();
}
// 7 清除document的移动事件,防止鼠标弹起
document.onmouseup = function(){
document.onmousemove = null;
}