事件基础
JavaScript 事件是由访问 Web 页面的用户引起的一系列操作。
当用户执行某些操作的时候,再去执行一系列代码。或者用来获取事件的详细信息,如鼠标位置、键盘按键等。
事件处理函数
javaScript可以处理的事件类型为:鼠标事件、键盘事件、HTML事件
所有的事件处理函数都会都有两个部分组成,on + 事件名称,函数体
1、鼠标事件
onclick 用户单击鼠标按钮或按下回车键时触发
ondblclick 用户双击主鼠标按钮时触发
onmousedown 用户按下鼠标还未弹起时触发
onmouseup 用户释放鼠标按钮时触发
// onmousedown和onmouseup可看做是单击鼠标事件的分解动作
onmouseover 鼠标移到某个元素上方时触发
onmouseout 鼠标移出某个元素上方时触发
onmousemove 鼠标指针在元素上移动时触发
onmouseenter onmouseleave
也是鼠标移入移出事件,但不支持事件冒泡
2、HTML事件
onload 页面或者资源完全加载后在 window 上面触发,
或框架集加载完毕后在框架集上触发。
onselect 用户选择文本框(input 或 textarea)中的一个或多个字符触发
onchange 文本框(input 或 textarea)内容改变且失去焦点后触发
onfocus 页面或者元素获得焦点时在 window 及相关元素上面触发
onblur 页面或元素失去焦点时在 window 及相关元素上触发
onsubmit 用户点击提交按钮在<form>元素上触发
onreset 用户点击重置按钮在<form>元素上触发
onresize 窗口或框架的大小变化时在 window 或框架上触发
onscroll 用户滚动带滚动条的元素时触发
3、键盘事件
onkeydown 用户按下键盘上任意键触发,如果按住不放,会重复触发
onkeypress 用户按下键盘上的字符键触发,如果按住不放,会重复触发
onkeyup 用户释放键盘上的键触发
组合键ctrlkey、altkey、shiftkey
altKey属性,bool类型,表示发生事件的时候alt键是否被按下
ctrlKey属性,bool类型,表示发生事件的时候ctrl键是否被按下
shiftKey属性,bool类型,表示发生事件的时候shift键是否被按下
keyCode/which兼容 获取用户按下键盘的哪个键
贪吃蛇小案例:通过键盘上下左右键控制div的移动
<div id="outer">
<div id="box"></div>
</div>
<script type="text/javascript">
var oBox = document.getElementById("box");
document.onkeydown = function(e){
var evt = e || window.event;
switch(evt.keyCode){
case 37: // 左移
oBox.style.left = oBox.offsetLeft-20+"px";
break;
case 38: // 上移
oBox.style.top = oBox.offsetTop-20+"px";
break;
case 39: // 右移
oBox.style.left = oBox.offsetLeft+20+"px";
break;
case 40: // 下移
oBox.style.top = oBox.offsetTop+20+"px";
break;
}
}
</script>
事件对象
当触发某个事件时,会产生一个事件对象,这个对象包含着所有与事件有关的信息。
包括导致事件的元素、事件的类型、以及其它与特定事件相关的信息。
通过事件绑定的执行函数是可以得到一个隐藏参数的 。
说明,浏览器会自动分配一个参数,这个参数其实就是 event 对象。
兼容性代码获取事件对象
oBox.onclick = function(e){
var evt = e || window.event;
}
// 距离可视区域的左边距距离,上边距距离
console.log(evt.clientX,evt.clientY);
// 距离页面的左边距距离,上边距距离
console.log(evt.pageX,evt.pageY);
// 距离事件源的左边距距离,上边距距离
console.log(evt.offsetX,evt.offsetY);
// 距离电脑显示屏幕的左边距距离,上边距距离
console.log(evt.screenX,evt.screenY);
事件冒泡
事件流 事件的传播顺序:捕获 事件源 冒泡
事件源 直接触发某个事件的DOM对象
冒泡 事件由最特定的目标到最不特定的目标的一个传播过程
<div id="outer">
<div id="inner"></div>
</div>
<script type="text/javascript">
var outer = document.getElementById("outer");
var inner = document.getElementById("inner");
document.onclick = function(e){
var evt = e || event;
// 得到事件源
console.log(evt.target || evt.srcElement);
//兼容性的写法
if(evt.stopPropagation){
//针对于现代浏览器的
evt.stopPropagation();
}else{
//最初是针对于IE
evt.cancelBubble = true;
}
}
</script>
事件默认行为及阻止方式
浏览器的默认行为:JavaScript事件本身所具有的属性,例如a标签的跳转,Submit按钮的提交,右键菜单,文本框的输入等。
阻止默认行为的方式
event.preventDefault(); //现代浏览器 不兼容IE低版本
event.returnValue = false; //针对IE,但现在很多浏览器也支持
return false; //兼容性最好的,但return之后的代码都将不会再执行
自定义右键菜单
oncontextmenu
document.oncontextmenu = function(e){
var evt = e || event;
var x = evt.clientX;
var y = evt.clientY;
oUl.style.display = "block";
oUl.style.left = x + "px";
oUl.style.top = y + "px";
}
DOM2级事件处理程序
区别:
1、DOM2级事件处理程序可以给同一DOM对象添加多个相同的事件处理函数
2、可以把事件获取方式由冒泡改为捕获
添加事件监听器:addEventListener(事件名,处理函数,布尔值)
移除事件监听器:removeEventListener(事件名,处理函数)
注意:事件名不带on,处理函数为函数指针,布尔值代表冒泡或捕获
如:element.addEventListener(“click”,foo,false);
IE下的事件监听器:
attachEvent(事件名,处理函数)
detachEvent(事件名,处理函数)
注意:事件名带on
封装事件监听函数
1、我们要给哪一个DOM对象,添加哪个类型,执行什么代码
2、浏览器兼容
function addEvent(domobj, type, fn) {
if(domobj.addEventListener) {
domobj.addEventListener(type, fn);
} else {
domobj.attachEvent("on" + type, fn);
}
}
function removeEvent(domobj, type, fn) {
if(domobj.removeEventListener) {
domobj.removeEventListener(type, fn);
} else {
domobj.detachEvent("on" + type, fn);
}
}
事件委托机制
利用事件冒泡的原理,把本应添加给某元素上的事件委托给他的父级(外层)。
主要目的:给新增的元素添加相同的事件。
好处:减少事件添加的次数,减少DOM操作。提高性能。
var oUl = document.querySelectorAll("ul")[0];
oUl.onclick = function(e){
var evt = e || event;
//console.log(evt.target || evt.srcElement);事件源,可得到是哪个li被点击
var _target = evt.target || evt.srcElement;
//console.log(_target.nodeName);
//toUpperCase() 字符串转大写 toLowerCase()字符串转小写
if(_target.nodeName.toUpperCase()=="LI"){
console.log("aa");
}
}
综合案例 九宫格拖拽交换位置
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
body{margin: 0;padding: 0;}
#wrap{
position: relative;
}
#wrap>div{position: absolute;
width: 100px;height: 100px;border-radius: 10px;
text-align: center;line-height: 100px;
font-size: 30px;color: #000000;
user-select : none;}
</style>
</head>
<body>
<div id="wrap"></div>
<script type="text/javascript">
var oWrap = document.getElementById("wrap");
// 创建结构,三行三列
var mt = ml = 10;
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
var oDiv = document.createElement("div");
oWrap.appendChild(oDiv);
oDiv.style.left = j * (oDiv.offsetWidth + ml) + "px";
oDiv.style.top = i * (oDiv.offsetHeight + mt) + "px";
// 设置随机颜色
oDiv.style.background = "rgb(" + Math.floor(Math.random() * 256) + "," + Math.floor(Math.random() * 256) + "," +
Math.floor(Math.random() * 256) + ")";
}
}
// 向单元格中添加字符
var arr = ["A", "B", "C", "D", "E", "F", "G", "H", "I"];
var aItems = oWrap.children;
for (var i = 0; i < aItems.length; i++) {
aItems[i].innerText = arr[i];
}
// 拖拽
for (var i = 0; i < aItems.length; i++) {
aItems[i].onmousedown = function(e) {
var evt = e || event;
var x = evt.offsetX;
var y = evt.offsetY;
var dragItem = this;
var cloneNode = dragItem.cloneNode();
cloneNode.style.border = "1px solid #cecece";
// 交换位置
// DOM结构顺序上的位置交换
oWrap.replaceChild(cloneNode, dragItem);
oWrap.appendChild(dragItem);
dragItem.style.zIndex = 1;
document.onmousemove = function(e) {
var evt = e || event;
var _left = evt.clientX - x;
var _top = evt.clientY - y;
// 去改变拖拽对象的样式,获取这个对象时,既不能用this,也不能用aItem[i]
// 不能用this的原因,this在这里指向document
// 不能用aItem[i],循环结束后,i值发生了变化
dragItem.style.left = _left + "px";
dragItem.style.top = _top + "px";
return false;
}
document.onmouseup = function() {
var disArr = []; //保存拖拽对象和单元格之间的距离
var newArr = [];
// 交换位置
for (var j = 0; j < aItems.length - 1; j++) {
var disX = dragItem.offsetLeft - aItems[j].offsetLeft;
var disY = dragItem.offsetTop - aItems[j].offsetTop;
var dis = Math.sqrt(Math.pow(disX, 2) + Math.pow(disY, 2));
disArr.push(dis);
newArr.push(dis);
}
// console.log(disArr);
// 找数组中的最小值及索引
disArr.sort(function(a, b) {
return a - b;
})
var minVal = disArr[0];
var minIndex = newArr.indexOf(minVal);
// 交换位置
dragItem.style.left = aItems[minIndex].style.left;
dragItem.style.top = aItems[minIndex].style.top;
aItems[minIndex].style.left = cloneNode.style.left;
aItems[minIndex].style.top = cloneNode.style.top;
oWrap.removeChild(cloneNode);
document.onmousemove = null;
document.onmouseup = null;
}
return false;
}
}
</script>
</body>
</html>