DOM事件编程
事件驱动编程:
所谓事件驱动,简单地说就是你点什么按钮(即产生什么事件),电脑执行什么操作(即调用什么函数).当然事件不仅限于用户的操作. 当对象处于某种状态时,可以发出一个消息通知,然后对这个消息感兴趣的程序就可以执行。
事件驱动编程中的几个核心对象:
1):事件源:谁发出事件通知,发出消息;也就是事件主体(通常指元素和标签);
2):事件名称:发出什么样的通知的名称,比如鼠标到我头上了,我被别人点了一下;
3):事件响应函数:谁对这个这个事件感兴趣,当这个事件发生时要执行什么样的操作;
4):事件对象:一般来说,当事件发生时,会产生一个描述该事件的具体对象,包括具体的参数等一起发给响应函数,好让他们通过事件对象来了解事件更加详细的信息。
很美丽动人的事故(事件):
有一天,在街上发现一个美女,小明伸出手在美女的脸蛋点击了一下,美女回头给了一巴掌,很痛!
事件源: 美女.
事件名称: 点击.
事件响应: 给了小明一巴掌.
事件对象: 时间,地点,人物,事情....
--------------------------------------------------------------------
示例:
<p style="color: red" id="p1">Hello world!</p>//事件源
function shout(e){//响应函数,监听函数
alert(e.clientX);//e事件对象
}
document.getElementById("p1").onclick=shout;//在事件源上绑定事件响应函数
JavaScript处理事件的基本机制:
1):对DOM元素绑定事件处理函数;
2):监听用户的操作;
3):当用户在相应的DOM元素上进行与绑定事件对应的操作时,事件处理函数做出响应;
4):将处理结果更新到 HTML 文档。
如何给HTML中的元素(事件源),绑定事件(有三种方式):
方式1:
直接在元素上设置onXxx属性.(xxx表示事件名称).
<p onclick="调用响应函数">P标签1</p>
使用JS内置的函数:
<p onclick="alert(123);">P标签1</p>
使用用户自定义的函数:
<p onclick="sayHello(this);">P标签1</p>
function sayHello(current){
//alert(current);//当前事件源对象
alert("123");
}
方式1:很简单也很直观,但是同一种的事件只能绑定一次.
方式2:
在元素对象上直接设置onXxx事件属性,再给事件属性设置响应的函数.
<p id="p2">P标签2</p>
window.onload = function(){
//方式二:在元素对象上设置onXxx属性,再给该属性设置响应函数(使用多)
//获取元素对象
var pEl = document.getElementById("p");
pEl.onclick = function(){
alert("我是方式二");
};
}
对应同一种事件,后绑定的事件响应函数会覆盖之前该事件绑定的响应函数.
方式3:
使用方法来完成对元素的监听.
IE浏览器:
[Object].attachEvent(“name_of_event_handler”, fnHandler);
name_of_event_handler>>事件操作前,必须加"on"!!!
多次添加监听后,触发顺序: 先添加,后执行
[Object].detachEvent(“name_of_event_handler”, fnHandler);
fnHandler : 移除时,传入的"事件响应函数",必须和添加时,传入的是同一个(通过相同标识符引用的那一个函数)
匿名函数,每次创建的都不同
W3C浏览器:
[Object].addEventListener(“name_of_event”, fnHandler);
name_of_event>>直接使用事件(操作)名称
多次添加监听后,触发顺序: 先添加,先执行
IE浏览器从IE9开始,也支持.
[Object].removeEventListener(“name_of_event”, fnHandler);
fnHandler : 移除时,传入的"事件响应函数",必须和添加时,传入的是同一个(通过相同标识符引用的那一个函数)
匿名函数,每次创建的都不同
window.onload = function(){
//方式三:设置监听事件
var divEle = document.getElementById("div1");
//W3C浏览器
// divEle.addEventListener("click", function(){
// alert("方式三");
// });
//IE浏览器
// divEle.attachEvent("onclick", function(){
// alert("IE浏览器");
// });
//通用
addListener(divEle, "click", function(){
alert("通用方式");
});
}; //定义一个通用的函数:可以为指定的元素设置指定的事件以及响应操作(解决浏览器兼容问题)
function addListener(ele, type, callBack){
if(ele.attachEvent){
//IE
ele.attachEvent("on"+type,callBack);
}else{
//W3C
ele.addEventListener(type,callBack);
}
}
事件其他相关的信息:
事件对象中的属性:
打字游戏简单设计:
打字游戏步骤:
1.准备一个游戏界面,提供开始游戏按钮
禁用按钮,在页面加载完毕,即时启用"开始游戏"按钮
2.对开始按钮,添加点击事件
2.1) 定时随机生成字符,并显示到页面中
2.1.1> 创建<lable>元素,并设置随机字符
<label style="position:absolute;top:30px;left:10px;background-color:red;width:20px;text-align:center;font-weight:bold;">I</label>
2.1.2> 把<lable>元素添加到body元素中
2.2) 让页面中的字符周期性向下移动
2.3) 对键盘输入内容,监听,对比输入内容,和游戏界面字母内容,一致则消除
示例代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="index.js"></script>
</head>
<body>
<input id="startBtn" type="button" value="开始游戏" disabled style="background-color: orange;">
<!--<label style="position: absolute;top: 30px;left: 20px;width: 30px;
background-color: orange;text-align: center;font-weight: bold;">M</label> -->
</body>
</html>
function startGame(){
//1:禁用[开始游戏]按钮
this.disabled = true; //2:周期性的生成<label>元素,在<label>元素中带有随机A~Z字符
setInterval(function(){
//1):创建带有随机字符的<label>元素
var labelEl = createLabel();
//2):把创建的<label>元素添加到文档中显示
document.body.appendChild(labelEl);
//3):把<label>元素添加到labelArray数组中
labelArray.push(labelEl);
}, 500); //3:让<label>元素,往下移动
setInterval(function(){
//浏览器高度
var windowHeight = document.documentElement.clientHeight - 30;
p(windowHeight);
for (var index = 0; index < labelArray.length; index++) {
//获取每一个<label>元素
var labelEl = labelArray[index];
//修改<label>元素距离浏览器顶端的位置
var oldHeight = parseInt(labelEl.style.top);
if(oldHeight < windowHeight){
var height = oldHeight + 10;
labelEl.style.top = height+"px";
}else{
//从界面上移除
labelEl.parentNode.removeChild(labelEl);
//从数组中移除
labelArray.splice(index, 1);
}
}
}, 100); //4:给当前文档注册键盘按下的事件
document.onkeydown = function(event){
//当前按下键的ASICC码
var keyCode = event.keyCode;
//获取当前ASICC码对应的字符
var charCode = String.fromCharCode(keyCode);
//判断当前页面是否存在对应的字符,若存在,则删除
for (var index = 0; index < labelArray.length; index++) {
var labelEl = labelArray[index];
if(labelEl.innerHTML == charCode){
//从界面上移除
labelEl.parentNode.removeChild(labelEl);
//从数组中移除
labelArray.splice(index, 1);
break;
}
}
}
} //创建带有随机A~Z字符的<label>元素
function createLabel(){
//1:生成65~91之间的随机数
var charCode = parseInt(Math.random() * 26) + 65;
//2:生成A~Z之间的随机字符
var ch = String.fromCharCode(charCode);
//3:创建<label>元素,并设置属性样式和文本内容,最后再返回<label>元素
//<label style="position: absolute;top: 30px;left: 20px;width: 30px;
//background-color: orange;text-align: center;font-weight: bold;">M</label>
var labelEl = document.createElement("label");
//设置属性样式
labelEl.style.position="absolute";
labelEl.style.top="40px";
labelEl.style.width="30px";
labelEl.style.backgroundColor="orange";
labelEl.style.textAlign="center";
labelEl.style.fontWeight="bold";
//随机生成距离浏览器左端的位置
//浏览器宽度
var windowWidth = document.documentElement.clientWidth - 30;
//p(windowWidth);
var width = 20 + Math.random() * windowWidth;
labelEl.style.left=width+"px"; //设置文本内容
labelEl.innerHTML = ch;
//返回
return labelEl;
} //==================
function p(data){
console.debug(data);
}
练习题:
复选框的全选:
示例代码:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>checkbox</title>
<script type="text/javascript" src="checkbox.js"></script>
</head>
<body>
请选择你的爱好:<br/>
<input type="checkbox" onchange="checkChange()" id="checkAll"/>全选/全不选<br/>
<div>
<input type="checkbox" name="hobby"/>打篮球
<input type="checkbox" name="hobby"/>踢足球
<input type="checkbox" name="hobby"/>上网
<input type="checkbox" name="hobby"/>写代码
<input type="checkbox" name="hobby"/>写文档
<input type="checkbox" name="hobby"/>查BUG
</div> <div>
<input type="button" id="btn_checkAll" onclick="checkAll(true)" value="全选"/>
<input type="button" onclick="checkAll(false)" value="全不选"/>
<input type="button" onclick="checkUnAll()" value="反选"/>
</div>
</body>
</html>
//全选和全不选
//check:为true表示全选
//check:为false表示为全不选
function checkAll(check){
//获取所有name为hobby的input标签
var hobbys = document.getElementsByName("hobby");
for (var index = 0; index < hobbys.length; index++) {
//把传递过来的check的类型赋值给每个hobby的checked属性
hobbys[index].checked = check;
}
} //反选
function checkUnAll(){
//获取所有name为hobby的input标签
var hobbys = document.getElementsByName("hobby");
for (var index = 0; index < hobbys.length; index++) {
//把每个hobby的checked属性取反再赋值给自身
hobbys[index].checked = !hobbys[index].checked;
}
} //全选/全不选
function checkChange(){
//获取该全选选择框自身的checked属性,再将该属性赋值给其他name为hobby的input标签
var checkbox = document.getElementById("checkAll");
checkAll(checkbox.checked);
}
列表移动:
示例代码:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>用户新增</title>
<script type="text/javascript" src="select.js"></script>
</head>
<body>
<table border="1">
<tr>
<td>
<select id="select1" style="width:100px" size="10" multiple="multiple">
<option value="选项1">选项1</option>
<option value="选项2">选项2</option>
<option value="选项3">选项3</option>
<option value="选项4">选项4</option>
<option value="选项5">选项5</option>
<option value="选项6">选项6</option>
<option value="选项7">选项7</option>
<option value="选项8">选项8</option>
<option value="选项9">选项9</option>
</select>
</td>
<td align="center">
<input type="button" onclick="this2other('select1','select2');" value="-->"/><br/>
<input type="button" onclick="thisAll2other('select1','select2');" value="==>"/><br/>
<input type="button" onclick="this2other('select2','select1');" value="<--"/><br/>
<input type="button" onclick="thisAll2other('select2','select1');" value="<=="/>
</td>
<td>
<select id="select2" style="width:100px" size="10" multiple="multiple"></select>
</td>
</tr>
</table>
</body>
</html>
//把某一边选中的选项移动到另一边
function this2other(srcSelect, targetSelect){
//获取两边列表对象
var src = document.getElementById(srcSelect);
var target = document.getElementById(targetSelect);
//获取源列表下所有的子节点
var options = src.getElementsByTagName("option");
for (var index = 0; index < options.length; index++) {
var option = options[index];//得到每一个option标签对象
//判断该标签是否有被选中
if(option.selected){
target.appendChild(option);
index--;
}
}
} //把某一边所有的选项移动到另一边
function thisAll2other(srcSelect, targetSelect){
//获取两边列表对象
var src = document.getElementById(srcSelect);
var target = document.getElementById(targetSelect);
//判断源列表是否存在子节点,若存在则移动到目标列表
while(src.hasChildNodes()){
target.appendChild(src.firstChild);
}
}
用户的添加-删除:
示例代码:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>用户新增</title>
<script type="text/javascript" src="user.js"></script>
</head>
<body>
<form name="userForm">
<center>
用户录入<br/>
用户名:<input id="username" name="username" type="text" size=15/>
E-mail:<input id="email" name="email" type="text" size=15/>
电话:<input id="tel" name="tel" type="text" size=15/>
<input type="button" value="添加" onclick="saveUser();"/>
<input type="button" value="删除所有" onclick="deleteAll();"/>
</center>
</form>
<hr/>
<table border="1" align="center" cellpadding=0 cellspacing=0 width=400>
<thead>
<tr>
<th>用户名</th>
<th>E-mail</th>
<th>电话</th>
<th>操作</th>
</tr>
</thead>
<tbody id="userTbody">
<tr>
<td>乔峰</td>
<td>qiao@163.com</td>
<td>18212345678</td>
<td><a href='#'>删除</a></td>
</tr>
</tbody>
</table> </body>
</html>
//添加一行数据
function saveUser(){
//获取输入框的数据
var username = document.getElementById("username").value;
var email = document.getElementById("email").value;
var tel = document.getElementById("tel").value; //创建html片段,如下
/* <tr>
<td>乔峰</td>
<td>qiao@163.com</td>
<td>18212345678</td>
<td><a href='#'>删除</a></td>
</tr>*/ //创建元素
var tr = document.createElement("tr");
var usernameTd = document.createElement("td");
var emailTd = document.createElement("td");
var telTd = document.createElement("td");
var hrefTd = document.createElement("td"); //给创建的td元素赋值(文本内容)
tr.id = new Date().getTime();
usernameTd.innerHTML = username;
emailTd.innerHTML = email;
telTd.innerHTML = tel;
hrefTd.innerHTML = "<a href='javascript:deleteUser("+tr.id+")'>删除</a>"; //设置层次关系
tr.appendChild(usernameTd);
tr.appendChild(emailTd);
tr.appendChild(telTd);
tr.appendChild(hrefTd);
document.getElementById("userTbody").appendChild(tr);
} //删除所有用户数据
function deleteAll(){
document.getElementById("userTbody").innerHTML = "";
} //删除某个用户数据
function deleteUser(id){
//根据传递的id获取用户对象
var user = document.getElementById(id);
//删除该用户
user.parentNode.removeChild(user);
}
今日小结: