第3章事件对象
3.1 概述
事件的触发,大部分情况下是用户的一种行为,也就是说,我们并不能确定用户什么时间触发;
而且,由于事件的传播机制,我们甚至不能确定事件具体触发在哪个节点;这是一件很不爽的事情;
如何解决呢?
事件发生以后,系统会调用我们写好的事件处理程序
系统会在调用处理程序时,将事件发生时有关事件的一切信息,封装成一个对象,
作为参数传给监听函数(事件处理程序),我们把这个对象称为事件对象。有关事件发生的一切信息,都包含在这个事件对象中;
根据事件类型的不同,事件对象中包含的信息也有所不同;如点击事件中,包含鼠标点击的横纵坐标位置,键盘事件中,包含键盘的键值等;
<body>
<divid="div">
<p>pppp</p>
</div>
<inputtype="text"value=""id="i">
</body>
<script>
vard=document.getElementById('div');
//鼠标事件
d.addEventListener('click',function(e){
console.log(e);
});
vari=document.getElementById('i');
//键盘事件
i.addEventListener('keydown',k);
functionk(e){
console.log(e);
}
</script>
3.2 事件对象中的常用属性及方法
3.2.1属性
event.bubbles:属性返回一个布尔值,表示当前事件是否会冒泡;event.eventPhase:返回一个整数值,表示事件流在传播阶段的位置
0:事件目前没有发生。1:事件目前处于捕获阶段。2:事件到达目标节点。3:事件处于冒泡阶段。
event.type:返回一个字符串,表示事件类型,大小写敏感;event.timeStamp:返回一个毫秒时间戳,表示事件发生的时间;
clientX、clientY :获取鼠标事件触发的坐标
<body>
<divid="d">
<pid="p">sdf</p>
</div>
</body>
<script>
varp=document.getElementById('p');
p.onclick=function(e){
//当前事件是否会冒泡
console.log(e.bubbles);
//事件目前所处的节点
console.log(e.eventPhase);
//事件类型
console.log(e.type);
//事件发生的时间戳
console.log(e.timeStamp);
}
</script>
3.2.2 事件代理/委托
event.target:对事件起源目标的引用,属性返回触发事件的那个节点。event.currentTarget:属性返回事件当前所在的节点,即正在执行的监听函数所绑定的那个节点。作为比较,target属性返回事件发生的节点。
vard=document.getElementById('d');
d.onclick=function(e){
//返回事件节点
console.log(e.currentTarget);
//返回触发节点
console.log(e.target);
}
由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件。这种方法叫做事件的代理也叫事件委托也有人称为事件代理
<head>
<title></title>
<metacharset="UTF-8">
<style>
div{padding: 40px}
#div3{width: 300px;height: 300px;border: 1pxsolidred;}
#div2{width: 200px;height: 200px;border: 1pxsolidred;}
#div1{width: 100px;height: 100px;border: 1pxsolidred}
</style>
</head>
<body>
<divid="div3">3
<divid="div2">2
<divid="div1">1</div>
</div>
</div>
</body>
<script>
vard=document.getElementById('div3');
d.onclick=function(e){
e.target.style.background='red';
}
</script>
3.3.3 阻止浏览器默认行为&阻止事件传播
event.preventDefault():方法取消浏览器对当前事件的默认行为,比如点击链接后,浏览器跳转到指定页面,或者按一下空格键,页面向下滚动一段距离。
event.stopPropagation():方法阻止事件在DOM中继续传播,防止再触发定义在别的节点上的监听函数
<body>
<divid="div2">2
<divid="div1">1
<aid="a"href="http://qq.com">清风陪你学习</a>
</div>
</div>
</body>
<script>
vard2=document.getElementById('div2');
vard1=document.getElementById('div1');
vara=document.getElementById('a');
d2.onclick=function(e){
alert('d2');
}
d1.onclick=function(e){
alert('d1');
}
a.onclick=function(e){
//阻止事件传播
//e.stopPropagation();
alert('a');
//阻止浏览器默认行为
e.preventDefault();
}
</script>
3.3 案例
验证密码的长度改变背景颜色
<inputtype="text"value=""id="txt"/>
<scriptsrc="common.js"></script>
<script>
//根据id获取文本框---失去焦点的事件
document.getElementById("txt").onblur=function () {
//判断文本框中输入的内容长度是否在6到10个之间,如果是这样的,则背景颜色为红色
if(this.value.length>=6&&this.value.length<=10){
this.style.backgroundColor="red";
}else{
this.style.backgroundColor="green";
}
};
</script>
div的高亮显示
<style>
div {
width: 200px;
height: 200px;
background-color: green;
float: left;
margin-right: 20px;
cursor: pointer;
border: 2pxsolidgreen;
}
</style>
<body>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<script>
//根据标签名字获取所有的div
vardivObjs=document.getElementsByTagName("div");
//循环遍历
for (vari=0; i<divObjs.length; i++) {
//为每个div添加鼠标进入事件
divObjs[i].onmouseover=mouseoverHandle;
//为每个div添加鼠标离开事件
divObjs[i].onmouseout=mouseoutHandle;
}
functionmouseoverHandle() {
this.style.border="2px solid red";
}
functionmouseoutHandle() {
//希望这个样式属性的值还原成默认的时候,值就是""空的字符串
this.style.border="";
}
</script>
鹦鹉学舌
<body>
<inputtype="text"id="t1"><br>
<inputtype="text"id="t2">
</body>
<script>
document.getElementById('t1').oninput=function(){
document.getElementById('t2').value=this.value;
}
</script>
飞机大战
<style>
div {
height: 500px;
width: 400px;
}
img {
height: 50px;
width: 50px;
position: absolute;
}
</style>
<body>
<div>
<imgsrc="/img/feiji.png"alt=""id="img"style="left:0px;top: 0px">
</div>
</body>
<script>
document.onkeydown=function (ev) {
varcode=ev.keyCode;
varimg=document.getElementById('img');
varx=parseInt(img.style.left), y=parseInt(img.style.top);
if (code==37) {
x=parseInt(img.style.left) -4+'px';
}
if (code==38) {
y=parseInt(img.style.top) -4+'px';
console.log(y);
}
if (code==39) {
x=parseInt(img.style.left) +4+'px';
}
if (code==40) {
y=parseInt(img.style.top) +4+'px';
}
img.style.left=x;
img.style.top=y;
}
</script>
· 鼠标点哪图片飞到哪里
思路:给整个dom绑定鼠标点击事件,获取点击位置后修改图片位置
<style>
img {
position: absolute;
width: 50px;
height: 50px;
}
</style>
<body>
<imgsrc="/img/c3.jpg"alt="">
</body>
<script>
varim=document.getElementsByTagName('img')[0];
document.onclick=function (e) {
im.style.left=e.clientX+'px';
im.style.top=e.clientY+'px';
}
</script>
· 跟着鼠标飞的天使
思路:点击图片后,给整个dom绑定鼠标移动事件,让图片跟随
<style>
img {
position: absolute;
width: 50px;
height: 50px;
}
</style>
<body>
<imgsrc="/img/c3.jpg"alt="">
</body>
<script>
varim=document.getElementsByTagName('img')[0];
im.onclick=function () {
document.onmousemove=function (e) {
im.style.left=e.clientX+'px';
im.style.top=e.clientY+'px';
}
}
</script>
· 实时获取鼠标在div内的坐标
<body>
<divid="div3">3
<pid="p"></p>
</div>
</body>
<script>
varp=document.getElementById('p');
document.getElementById('div3').onmousemove=function(e){
p.innerHTML=e.clientX+','+e.clientY;
p.style.top=e.clientY+"px";
p.style.left=e.clientX+"px";
}
</script>
· 一次性事件案例(下载按钮点一次则失效)
<body>
<inputtype="button"id="btn"value="下载">
</body>
<script>
varbtn=document.getElementById('btn');
functionf(){
alert(123);
btn.removeEventListener('click',f);
}
btn.addEventListener('click',f);
</script>
第4章节点操作
页面元素节点的操作,都离不开DOM对象
4.1 节点操作1
document.createElement()用来生成网页元素节点,参数为元素的标签名;
document.createTextNode()用来生成文本节点,参数为所要生成的文本节点的内容;
node.appendChild()接受一个节点对象作为参数,将其作为最后一个子节点,插入当前节点;
node.hasChildNodes()返回一个布尔值,表示当前节点是否有子节点
node.removeChild()接受一个子节点作为参数,用于从当前节点移除该子节点
node.cloneNode()用于克隆一个选中的节点。它接受一个布尔值作为参数,表示是否同时克隆子节点,默认是false,即不克隆子节点。注意:不会克隆绑定到该元素上的事件;
node.innerHTML返回该元素包含的 HTML 代码。该属性可读写,常用来设置某个节点的内容;(不属于W3C DOM规范)
node.innerText
返回该元素包含的内容。该属性可读写
<body>
<divid="d">
<span>111</span>
</div>
</body>
<script>
//创建元素节点
varp=document.createElement('p');
//创建文本节点
vart=document.createTextNode('气味');
//添加节点
p.appendChild(t);
vard=document.querySelector('#d')
d.appendChild(p);
//判断是否有子节点
if(d.hasChildNodes('span')){
vars=document.querySelector('span');
//删除子节点
d.removeChild(s);
}
// 克隆一个节点
varc=d.cloneNode(true);
d.appendChild(c);
//操作选中元素的HTML代码,有值则是设置,无值则是获取
alert(d.innerHTML);
console.log(document.getElementById('d').innerText);
console.log(document.getElementById('d').innerHTML);
</script>
案例:
点击按钮创建img节点,添加到body中
<body>
<inputtype="button"value="我要图"id="btn">
</body>
<script>
varbtn=document.getElementById('btn');
btn.onclick=function(){
// var img =document.createElement('img');
// img.src ='/img/c2.jpg';
//document.getElementsByTagName('body')[0].appendChild(img);
// 直接
document.getElementsByTagName('body')[0].innerHTML+="<imgsrc='/img/c3.jpg'>";
}
</script>
动态创建文本框
<body>
<inputtype="button"value="++"id="btn">
<divid="bo"></div>
</body>
<script>
varbtn=document.getElementById('btn');
btn.onclick=function () {
//document.getElementById('bo').innerHTML += '<inputtype="text">';
varinp=document.createElement('input');
document.getElementById('bo').appendChild(inp);
}
</script>
4.2 节点属性
4.2.1 原生属性
HTML元素节点的标准属性(即在标准中定义的属性),会自动成为元素节点对象的属性
<body>
<divid="d"a="b"></div>
</body>
<script>
vard=document.querySelector('#d');
//获取原有属性值
console.log(d.id);
//修改原有属性值
d.id='ff';
console.log(d.a); // undefined
</script>
4.2.2 属性操作的标准方法
node.getAttribute()返回当前元素节点的指定属性。如果指定属性不存在,则返回null;
node.setAttribute()为当前元素节点新增属性。如果同名属性已存在
<body>
<divid="d"></div>
</body>
<script>
vard=document.querySelector('#d');
//设置属性,有则修改,无则添加,可设置非标准属性
d.setAttribute('id','ffdd');
d.setAttribute('aa','kk');
//获取属性值,可获取非标准属性
console.log(d.getAttribute('aa'));
</script>
node.hasAttribute()返回一个布尔值,表示当前元素节点是否包含指定属性
node.removeAttribute()从当前元素节点移除属性
//如果有id属性
if(d.hasAttribute('id')){
//删除id属性
d.removeAttribute('id');
}
4.3 节点操作2
node.nextElementSibling返回紧跟在当前节点后面的第一个同级Element节点,如果当前节点后面没有同级节点,则返回null;
node.previousElementSibling返回紧跟在当前节点前面的第一个同级Element节点,如果当前节点前面没有同级节点,则返回null;
node.parentElement返回当前节点的父级Element节点;
node.childNodes返回一个NodeList集合,成员包括当前节点的所有子节点(注意空格回车也算)。
node.firstChild
返回树中节点的第一个子节点,如果节点是无子节点,则返回null。
node.lastChild
返回该节点的最后一个子节点,如果该节点没有子节点则返回null。
<body>
<divid="d1">
<pid="p1">11111</p>
<pid="p2">222</p>
<pid="p3">33333</p>
<pid="p4">4444</p>
</div>
<divid="d2">
<pid="p5">55555</p>
<pid="p6">66666</p>
</div>
</body>
<script>
varp2=document.querySelector('#p2');
//下一个兄弟节点
p2.nextElementSibling.style.background='red';
//上一个兄弟节点
p2.previousElementSibling.style.background='red';
//父级节点
p2.parentElement.style.background='red';
vard1=document.querySelector('#d1');
//所有子节点列表
d1.childNodes[3].style.background='red';
</script>
4.4 CSS样式操作
每个DOM对象都有style属性,我们可以直接操作,用来读写行内CSS样式。之前,我们已经简单的使用过JS控制元素的CSS样式;在具体使用的时候还有一些需要重点注意的细节:
1. 名字需要改写,将横杠从CSS属性名中去除,然后将横杠后的第一个字母大写:
比如background-color写成backgroundColor
2. 属性值都是字符串,设置时必须包括单位:
比如,divStyle.width的值不能写为100,而要写为100px
<body>
<divid="d1"style="width:400px;height:200px;border: 1px solid red"></div>
</body>
<script>
vard1=document.querySelector('#d1');
d1.onclick=function(){
//赋值则是设置
d1.style.backgroundColor='red';
//不赋值则是获取
alert(d1.style.width);
}
</script>
以上代码中,我们获取的CSS样式,均是行内样式;
如果将样式表写在 style 标签内,我们将无法获取和修改;
getComputedStyle()接受一个节点对象,返回该节点对象最终样式信息的对象,所谓“最终样式信息”,指的是各种CSS规则叠加后的结果。
注意: getComputedStyle()是window对象下的方法,不是DOM对象
<style>
#d1{
width: 200px;height: 200px;
border: 1pxsolidred;
}
</style>
<body>
<divid="d1"></div>
</body>
<script>
vard1=document.querySelector('#d1');
d1.onclick=function(){
//获取不到
console.log(d1.style.width);
//获取计算后的样式
console.log(getComputedStyle(d1).width);
}
</script>
点击变大小案例:
<head>
<metacharset="UTF-8">
<title>Document</title>
<style>
#d1{
width: 200px;height: 200px;
border: 1pxsolidred;
}
</style>
</head>
<body>
<divid="d1"></div>
</body>
<script>
vard1=document.querySelector('#d1');
d1.onclick=function(){
varw=parseInt(getComputedStyle(d1).width);
varh=parseInt(getComputedStyle(d1).height);
d1.style.width=w+10+'px';
d1.style.height=h+10+'px';
}
</script>
其他方法和属性:
document.documentURI返回文档的 URL。
node.replaceChild(newChild,oldChild) 用指定的节点替换当前节点的一个子节点,并返回被替换掉的节点。
node.insertBefore(): parentElement.insertBefore(newElement,referenceElement);
4.5 案例
节点方式隔行变色
<body>
<inputtype="button"value="隔行变色"id="btn"/>
<ulid="uu">
<li>雪花啤酒</li>
<li>金士百啤酒</li>
<li>青岛啤酒</li>
<li>燕京啤酒</li>
<li>百威啤酒</li>
<li>哈尔滨啤酒</li>
<li>乐宝啤酒</li>
<li>崂山啤酒</li>
</ul>
</body>
<script>
//点击按钮,所有的li隔行变色---奇红偶黄
document.getElementById("btn").onclick=function () {
varcount=0;
//要获取ul中所有的子节点
varnodes=document.getElementById("uu").childNodes;
for (vari=0; i<nodes.length; i++) {
varnode=nodes[i];
//判断这个节点是不是li
if (node.nodeType=="1"&&node.nodeName=="LI") {
node.style.backgroundColor=count%2==0?"red" : "yellow";
count++;//记录li标签的个数
}
}
};
</script>
全选和全不选
<style>
table {
border-collapse: collapse;
border-spacing: 0;
border: 1pxsolid#c0c0c0;
width: 500px;
}
th,
td {
border: 1pxsolid#d0d0d0;
color: #404060;
padding: 10px;
}
</style>
<body>
<table>
<thead>
<tr>
<th>
<inputtype="checkbox"id="th"/>
</th>
<th>菜名</th>
<th>饭店</th>
</tr>
</thead>
<tbodyid="tb">
<tr>
<td>
<inputtype="checkbox"/>
</td>
<td>红烧肉</td>
<td>田</td>
</tr>
<tr>
<td>
<inputtype="checkbox"/>
</td>
<td>西红柿鸡蛋</td>
<td>田</td>
</tr>
<tr>
<td>
<inputtype="checkbox"/>
</td>
<td>油炸</td>
<td>田</td>
</tr>
<tr>
<td>
<inputtype="checkbox"/>
</td>
<td>清蒸</td>
<td>田</td>
</tr>
</tbody>
</table>
</body>
<script>
document.getElementById('th').onclick=function () {
vartb=document.getElementsByTagName('input');
if (this.checked==true) {
// console.log(tb);
for (vari=0; i<tb.length; i++) {
tb[i].checked=true;
}
} else {
for (vari=0; i<tb.length; i++) {
tb[i].checked=false;
}
}
}
</script>
作业,实现反选
表格鼠标悬浮高亮(接上一个案例)
vart=document.getElementsByTagName('tbody')[0];
t.onmouseover=function(e){
e.target.parentElement.style.background='#F5F5F5';
}
t.onmouseout=function(e){
e.target.parentElement.style.background='#fff';
}
动态可编辑表格
<style>
table {
border-collapse: collapse;
border-spacing: 0;
border: 1pxsolid#c0c0c0;
width: 500px;
}
th,
td {
border: 1pxsolid#d0d0d0;
color: #404060;
padding: 10px;
}
</style>
<body>
<inputtype="button"value="添加一行"id="addrow">
<table>
<thead>
<tr>
<td>菜名</td>
<td>饭店</td>
<td>厨师</td>
</tr>
</thead>
<tbodyid="tb"></tbody>
</table>
</body>
<script>
vartbs=document.getElementsByTagName('table')[0];
tbs.onclick=function (e) {
varclicks=e.target;
if (clicks.nodeName=='TD') {
// var inp = document.createElement('input');
// inp.value = clicks.innerText;
// console.log(clicks.parentElement);
clicks.innerHTML='<input value='+clicks.innerText+'>';
tbs.getElementsByTagName('input')[0].onblur=function () {
clicks.innerHTML=this.value;
}
}
}
varaddrow=document.getElementById('addrow');
addrow.onclick=function(){
vartr=document.createElement('tr');
for(vari=0; i<3;i++){
tr.appendChild(document.createElement('td'));
}
document.getElementById('tb').appendChild(tr);
}
</script>
"我是Spirit_Breeze,中文<晟世清风>,在这纷纷乱世之中,祈望能有一股清流之风." 本人从事销售,不甘心于口舌之利,突然对代码和框架充满兴趣,遂之研究研究,欢迎研究讨论,转载请备注地址和作者,谢谢