Javascript操作DOM的API及事件详解相关笔记(二)
◆事件源 --> 唐僧
◆事件类型 -->念咒
◆事件处理程序 --> 孙悟空头疼
2.在js中 事件源指的是 引发后续事件的标签,事件指的是 js已经定义好的可以直接使用的事件,事件驱动程序指的是 对样式和html的操作(Dom操作)。
3.获取事件源的四种方式
★getElement前缀表示获取一个元素对象,getElements前缀表示获取一个数组对象。
◆通过元素的id属性值来获取事件源,返回值是一个元素对象,var div=document.getElementById("box");
◆通过元素的标签名来获取事件源,返回值是一个数组对象,元素的数组,var arr1=document.getElementsByTagName("div");
◆通过元素的class属性来获取事件源,这种方式在IE678里不支持,返回值是一个数组对象,元素的数组,var arr2=document.getElementsByClassName("classname");
◆通过元素的name属性来获取事件源,返回值是一个数组对象,元素的数组,var arr3=document.getElementsByName("name");
4.事件绑定的三种方式
◆匿名函数绑定的方式,事件源.事件=function(){//事件驱动程序};
◆普通函数绑定的方式,function fn(){} 事件源.事件=fn;
◆行内绑定的方式,function fn(){} <div 事件="fn()"></div>
5.对页面标签元素进行操作的顺序是,首先获取事件源,然后给事件源绑定事件,最后书写事件驱动程序(功能代码)
6.使用对象的操作属性的方法来添加或者获取及删除时,要以页面标签实际的属性为主,而通过对象的操作属性 对象.属性或者对象["属性"]时,要以页面标签转换为对象后的对象的属性为主,如页面标签转换后的class属性不再是class属性了,而是className,但是使用getAttribute()/setAttribute()/removeAttribute()时,是以页面的标签明码显示的属性为主,如获取class属性则是对象.getAttribute("class");而不是对象.getAttribute("className");,设置与删除也是如此。
7.通过访问关系获取节点的方式:
◆直接获取当前节点:document.getElementById("id");也能通过类名 标签名 名字 来获取
◆间接获取上一个兄弟节点:当前节点.previousElementSibling,但是这种获取的方式在IE678中不支持,因为在IE678中使用的是当前节点.previousSibling,可是随着时代的更新,节点的类型增多,比如元素节点啊、属性节点、文本节点等等,所以当前节点.previousSibling不但可以获取元素节点还有可能会获取到其它节点,于是一个新的属性previousElementSibling出现了,它用来专门获取元素节点,但是为了兼容IE678,所以需要采取一个新的写法,如:var pre=当前节点.previousElementSibling || 当前节点.previousSibling;,这样表示,如果IE678访问则会使用当前节点.previousSibling,否则就使用当前节点.previousElementSibling,通过||运算符,表面上是拿两个值作为bool值来进行逻辑判断,如果哪一边为true就会返回先为true的那一边的实际值。
◆间接获取下一个兄弟节点:当前节点.nextElementSibling,但是这种获取的方式在IE678中不支持,因为在IE678中使用的是当前节点.nextSibling,可是随着时代的更新,节点的类型增多,比如元素节点啊、属性节点、文本节点等等,所以当前节点.previousSibling不但可以获取元素节点还有可能会获取到其它节点,于是一个新的属性nextElementSibling出现了,它用来专门获取元素节点,但是为了兼容IE678,所以需要采取一个新的写法,如:var pre=当前节点.nextElementSibling || 当前节点.nextSibling;,这样表示,如果IE678访问则会使用当前节点.nextSibling,否则就使用当前节点.nextElementSibling,通过||运算符,表面上是拿两个值作为bool值来进行逻辑判断,如果哪一边为true就会返回先为true的那一边的实际值。
◆间接获取父节点:当前节点.parentNode;表示获取当前节点的父节点
◆间接获取自己的第一个子节点:当前节点.firstElementChild,但是这种获取的方式在IE678中不支持,因为在IE678中使用的是当前节点.firstChild,可是随着时代的更新,节点的类型增多,比如元素节点啊、属性节点、文本节点等等,所以当前节点.firstSibling不但可以获取元素节点还有可能会获取到其它节点,于是一个新的属性firstElementChild出现了,它用来专门获取元素节点,但是为了兼容IE678,所以需要采取一个新的写法,如:var pre=当前节点.firstElementChild || 当前节点.firstChild;,这样表示,如果IE678访问则会使用当前节点.firstChild,否则就使用当前节点.firstElementChild,通过||运算符,表面上是拿两个值作为bool值来进行逻辑判断,如果哪一边为true就会返回先为true的那一边的实际值。
◆间接获取自己的最后一个子节点:当前节点.lastElementChild,但是这种获取的方式在IE678中不支持,因为在IE678中使用的是当前节点.lastChild,可是随着时代的更新,节点的类型增多,比如元素节点啊、属性节点、文本节点等等,所以当前节点.lastChild不但可以获取元素节点还有可能会获取到其它节点,于是一个新的属性lastElementChild出现了,它用来专门获取元素节点,但是为了兼容IE678,所以需要采取一个新的写法,如:var pre=当前节点.firstElementChild || 当前节点.lastChild;,这样表示,如果IE678访问则会使用当前节点.lastChild,否则就使用当前节点.lastElementChild,通过||运算符,表面上是拿两个值作为bool值来进行逻辑判断,如果哪一边为true就会返回先为true的那一边的实际值。
◆间接获取所有的子节点:当前节点.children,获取所有的元素节点 但是在IE678中还可能会获取注释节点,当前节点.childNodes,获取所有的子节点 ,会包括元素节点、属性节点、文本节点等等,需要自己使用循环来判断,取你想要的节点然后放到一个新的数组中去,比如把所有的元素节点放到一个数组中去。
★如果你像找到自己所有的兄弟节点,那么可以使用当前节点.parentNode.children,这个可以找到所有的兄弟元素节点,而当前节点.parentNode.childNodes,这个可以找到所有的兄弟节点,包括元素节点、属性节点、文本节点等等,可以自己使用for循环把想要的节点放到一个新的数组中去。
◆
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>对象的访问关系及兼容性写法</title>
<style type="text/css">
li {
list-style:none;
width: 100px;
height: 100px;
margin:20px auto;
background-color: #000;
}
</style>
</head>
<body>
<ul>
<li class="box1"></li>
<li class="box2"></li>
<li id="box3"></li>
<li class="box4"></li>
<li class="box5"></li>
</ul>
<script>
//1.获取当前节点
var box3=document.getElementById("box3");
box3.style.backgroundColor="#0f0";
console.log(box3);
//2.获取上一个兄弟节点
// var box2=box3.previousElementSibling; //IE 678 不支持 其它浏览器支持
// var box2=box3.previousSibling;//IE 678支持 在IE678中没有文本节点 但是在除了IE678之外的其它浏览器可能会获取到非元素节点 如文本节点等等
//2.1.兼容性写法
var pre=box3.previousElementSibling || box3.previousSibling;
console.log(pre);
pre.style.backgroundColor="#0ff";
//3.获取下一个兄弟节点
// var box4=box3.nextElementSibling;//IE 678 不支持 其它浏览器支持
// var box4=box3.nextSibling;//IE 678支持 在IE678中没有文本节点 但是在除了IE678之外的其它浏览器可能会获取到非元素节点 如文本节点等等
//3.1.兼容性写法
var next=box3.nextElementSibling || box3.nextSibling;
console.log(next);
next.style.backgroundColor="#ff0";
//4.获取当前节点的父节点
var parent=box3.parentNode;
console.log(parent);
parent.style.backgroundColor="#f00";
//5.获取当前节点的父节点中的第一个节点
// var first=parent.firstElementChild;//IE 678 不支持 其它浏览器支持
// var first=parent.firstChild;//IE 678支持 在IE678中没有文本节点 但是在除了IE678之外的其它浏览器可能会获取到非元素节点 如文本节点等等
//5.1兼容性写法
var first=parent.firstElementChild || parent.firstChild;
console.log(first);
first.style.backgroundColor="#f0f";
//6.获取当前节点的父节点中的最后一个节点
// var last=parent.lastElementChild;//IE 678 不支持 其它浏览器支持
// var last=parent.lastChild;//IE 678支持 在IE678中没有文本节点 但是在除了IE678之外的其它浏览器可能会获取到非元素节点 如文本节点等等
//6.1兼容性写法
var last=parent.lastElementChild || parent.lastChild;
console.log(last);
last.style.backgroundColor="#00f";
//7.获取所有的子节点
var childen=parent.children;//获取所有的元素节点 但是在IE678中还可能会获取注释节点
console.log(childen);
var childNodes=parent.childNodes;//获取所有的子节点 //包括元素节点 属性节点 文本节点等等
console.log(childNodes);
</script>
</body>
</html>
8.获取节点的名称、节点的类型、节点的值
◆获取节点的名称:当前节点.nodeName,节点分为很多种,元素节点的名称就是标签名,属性节点的名称就是属性名,文本节点的名称统一叫做#text。
◆获取节点的类型:当前节点.nodeType,节点分为很多种,元素节点的类型 是1,属性节点的类型是2,文本节点的类型是3。
◆获取节点的值:当前节点的.nodeValue,节点分为很多种,元素节点的值不是那个value属性而是nodeValue属性,默认元素节点的值都为null,属性节点的值为对应属性值,如果你获取的属性节点为value属性,那么对应的节点的值(nodeValue)就是value属性的属性值,如果你获取的属性节点是id属性,那么对应的节点的值则为id属性的属性值,文本节点的的值为对应的文本值,也就是纯文本。
★如果想获取元素节点的value属性的值,那么请先获取这个元素节点的对应的value属性节点,通过元素节点.getAttributeNode("value");来获取,然后通过获取属性节点的值(nodeValue)来获取value属性的值。
◆
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>节点的类型、名称、值</title>
</head>
<body>
<div id="box" value="hahah">你好</div>
<script>
var ele=document.getElementById("box");//元素节点
var att=ele.getAttributeNode("id");//属性节点
var txt=ele.firstChild;//元素节点内部只有一个文本 所以第一个子节点就是文本节点
var atts=ele.attributes;
console.log(atts);
console.log(ele.nodeName);//div
console.log(ele.nodeType);//1
console.log(ele.nodeValue);//null
console.log(att.nodeName);//id
console.log(att.nodeType);//2
console.log(att.nodeValue);//box
console.log(txt.nodeName);//#text
console.log(txt.nodeType);//3
console.log(txt.nodeValue);//你好
</script>
</body>
</html>
9.列表隔行变色与选项卡切换
◆列表隔行变色
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>列表隔行变色变样式</title>
<style type="text/css">
* {
padding: 0;
margin: 0;
}
ul {
width: 500px;
margin: 100px 0px 0px 200px;
background-color: #000;
text-align: center;
overflow: hidden;
}
li {
list-style: none;
height: 40px;
font: 500 16px/40px "microsoft yahei";
margin: 10px 10px;
}
</style>
</head>
<body>
<ul>
<li>北京股指 3063.31-22.18 (-0.72%)</li>
<li>上海股指 3063.31-22.18 (-0.72%)</li>
<li>广州股指 3063.31-22.18 (-0.72%)</li>
<li>深圳股指 3063.31-22.18 (-0.72%)</li>
<li>北京股指 3063.31-22.18 (-0.72%)</li>
<li>上海股指 3063.31-22.18 (-0.72%)</li>
<li>广州股指 3063.31-22.18 (-0.72%)</li>
<li>深圳股指 3063.31-22.18 (-0.72%)</li>
</ul>
<script>
//普通版
// var liArr=document.getElementsByTagName("li");
// for(var i=0;i<liArr.length;i++){
// if(i%2===0){
// liArr[i].style.backgroundColor="#0f0";
// }else {
// liArr[i].style.backgroundColor="#f00";
// }
// }
//高级版
var ele = document.getElementsByTagName("ul")[0];
var liArr = ele.childNodes;
var newArr = [];
for (var i = 0; i < liArr.length; i++) {
if (liArr[i].nodeType === 1) {
newArr.push(liArr[i]);
}
}
newArr.forEach(function(element,index,array){
if(index%2===0){
element.style.backgroundColor="#f00";
}else{
element.style.backgroundColor="#0f0";
}
})
</script>
</body>
</html>
◆选项卡切换:
◇简单版
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>tab选项卡切换( js版本 )</title>
<style>
* {
padding: 0;
margin: 0;
}
.box {
width: 500px;
height: 400px;
margin: 100px auto 0px;
border: 1px solid #ccc;
}
ul, li {
list-style: none;
}
ul {
width: 110%;
text-align: center;
overflow: hidden;
}
ul li {
float: left;
width: 100px;
height: 40px;
font: 700 20px/40px "microsoft yahei";
background-color: #ff0;
cursor: pointer;
}
.box div {
height: 360px;
text-align: center;
font: 500 200px/360px "\u5b8b\u4f53";
display: none;
}
div.show {
display: block;
background-color: #0f0;
}
.current {
background-color: #0f0;
}
</style>
<script>
window.onload = function () {
//需求:选中tab选项卡中某一项时,那一项显示为选中状态,然后对应的内容部分要显示出来
//思路: 选中选项卡时 添加类,对应的内容部分也添加类,使用for循环给选项卡每一项都要设置移入事件,还要在for循环绑定事件的时候给每一个选项卡设置一个自定义的索引属性,以便在事件面找到相应的内容部分,给相应的内容部分添加类。
//步骤:
//1 获取事件源及相关元素
//2 绑定事件
//3 书写事件驱动程序
//1 获取事件源及相关元素
var ul = box.getElementsByTagName("ul")[0];
var liArr = ul.getElementsByTagName("li");
var divArr = box.getElementsByTagName("div");
//2 绑定事件
for (var i = 0; i < liArr.length; i++) {
//3 书写事件驱动程序
//设置每一次绑定的选项卡的自定义索引属性
liArr[i].index = i;
liArr[i].onmouseover = function () {
//排他思想 先干掉全部 然后再复活自己
for (var j = 0; j < liArr.length; j++) {
//干掉全部
liArr[j].className = "";
divArr[j].className = "";
}
//复活自己
this.className = "current";
divArr[this.index].className = "show";
}
}
}
</script>
</head>
<body>
<div class="box" id="box">
<ul>
<li class="current">仙女</li>
<li>熊猫</li>
<li>小熊</li>
<li>考拉</li>
<li>袋鼠</li>
</ul>
<div class="show">仙女</div>
<div>熊猫</div>
<div>小熊</div>
<div>考拉</div>
<div>袋鼠</div>
</div>
</body>
</html>
◇实用版
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>tab选项卡切换复杂版( js版本 )</title>
<style>
* {
padding: 0;
margin: 0;
}
.box {
width: 500px;
height: 400px;
margin: 100px auto 0px;
border: 1px solid #ccc;
}
ul, li {
list-style: none;
}
ul {
width: 110%;
text-align: center;
overflow: hidden;
}
ul li {
float: left;
width: 100px;
height: 40px;
font: 700 20px/40px "microsoft yahei";
background-color: #ff0;
cursor: pointer;
}
.box div {
height: 360px;
text-align: center;
font: 500 200px/360px "\u5b8b\u4f53";
display: none;
}
div.show {
display: block;
background-color: #0f0;
}
.current {
background-color: #0f0;
}
</style>
<script>
//封装的改变选项卡时改变其对应的内容
function changeTab(obj) {
//1 获取事件源及相关元素
var ul = obj.getElementsByTagName("ul")[0];
var liArr = ul.getElementsByTagName("li");
var divArr = obj.getElementsByTagName("div");
//2 绑定事件
for (var i = 0; i < liArr.length; i++) {
//3 书写事件驱动程序
//设置每一次绑定的选项卡的自定义索引属性
// liArr[i].index = i;
liArr[i].setAttribute("index", i);
liArr[i].onmouseover = function () {
//排他思想 先干掉全部 然后再复活自己
for (var j = 0; j < liArr.length; j++) {
//干掉全部
// liArr[j].className = "";
// divArr[j].className = "";
liArr[j].removeAttribute("class");
divArr[j].removeAttribute("class");
}
//复活自己
// this.className = "current";
// divArr[this.index].className = "show";
this.setAttribute("class", "current");
divArr[this.getAttribute("index")].setAttribute("class", "show");
}
}
}
window.onload = function () {
//需求:选中tab选项卡中某一项时,那一项显示为选中状态,然后对应的内容部分要显示出来,最后再添加一个相同的tab盒子,上下两个tab盒子无不干扰
//思路: 选中选项卡时 添加类,对应的内容部分也添加类,使用for循环给选项卡每一项都要设置移入事件,还要在for循环绑定事件的时候给每一个选项卡设置一个自定义的索引属性,以便在事件面找到相应的内容部分,给相应的内容部分添加类。
//思路2:除了添加类之外 还要移除掉没有选中的选项卡及对应内容中的类,不要设置那些没选中的类属性为空
//思路3:代码可复用 互相不干扰 ,封装函数,把tab盒子的父容器对象作为参数传递进去,从而达到 两个tab盒子互相不干扰。
//步骤:
//1 获取事件源及相关元素
//2 绑定事件
//3 书写事件驱动程序
/////调用的方式有两种 一种是通过id 一个一个的调用,一种是通过class 使用for循环来调用
//第一种方式:调用改变选项卡时改变其对应的内容 方法 将父容器对象传递进去
// changeTab(box);//调用
// changeTab(box2);//调用
//第二种方式:通过获取相同类的对象 然后使用for循环来调用它
var boxArr=document.getElementsByClassName("box");
for(var i=0;i<boxArr.length;i++){
changeTab(boxArr[i]);
}
}
</script>
</head>
<body>
<div class="box" id="box">
<ul>
<li class="current">仙女</li>
<li>熊猫</li>
<li>小熊</li>
<li>考拉</li>
<li>袋鼠</li>
</ul>
<div class="show">仙女</div>
<div>熊猫</div>
<div>小熊</div>
<div>考拉</div>
<div>袋鼠</div>
</div>
<div class="box" id="box2">
<ul>
<li class="current">仙女</li>
<li>熊猫</li>
<li>小熊</li>
<li>考拉</li>
<li>袋鼠</li>
</ul>
<div class="show">仙女</div>
<div>熊猫</div>
<div>小熊</div>
<div>考拉</div>
<div>袋鼠</div>
</div>
</body>
</html>