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;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; 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; 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="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="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); }
今日小结: