这两天更进一步的了解了JS,老师让我们用原生的js编写图片切换和改变点击按钮样式,就是让我们学会怎么去把一个问题拆分,怎么将一个大问题拆分成许多的小问题,再用函数封装起来。比如一个点击按钮,让其点击时背景色发生改变,点击另一个时,上一个按钮要变回原来本有的颜色:这个问题用jquery,一行代码就搞定,但是用原生js就得分三个部分来考虑:
1.添加改变背景的样式。
2.怎么获取到除了当前点击的按钮以外其他的兄弟节点。
3.怎么去除按钮的样式属性。
也讲了事件委托,实现了可以删除新添加的元素的功能。后面我会把代码贴出来。
这两天上课讲得一些笔记:
1.需要注意的两个细节:(1)、不要随意修改别的对象的属性值,比如图片切换这个例子,要获取li的索引时,不能改变节点的index属性。
(2)、实现某个功能时,要封装好业务逻辑,做到改变dom节点时,不用改变业务逻辑。
2.属性:(1)、dom.parentNode :dom节点的父元素。
(2)、dom.children : Element的属性,代表元素节点的所有子元素,Element是Node的扩展,也是他多种类型中的一种。
(3)、dom.childNode: Node中的属性,代表节点的所有子元素,而节点又分为元素节点、文本节点、属性节点、注释节点、文档节点等。
e.g:
Node的children属性为undefined.因为Node代表DOM中的节点,而上面也提到了children只是元素节点的属性。
(4)、dom.className : 为节点添加class名。
3.方法 : (1)、dom.appendChild :appendChild() 方法向节点添加最后一个子节点。
(2)、dom.removeChild: removeChild() 方法指定元素的某个指定的子节点,以 Node 对象返回被删除的节点,如果节点不存在则返回 null。
4. push()方法 : 用法: arr.push(Arr[i]) ,将Arr的第i个元素插入到arr数组中。
5. "==" 和"==="的区别: "=="只会比较值是否相等,比如 1 == "1" 是对的,但会true,而"==="是值和数据类型都会比较,完全相等才返回true,所以1 === "1" 返回false。
6. 关于函数讲了两个重要的点:(1)、函数可以被调用很多次,调用执行后,函数就会被销毁,这是函数的机制。
(2)、闭包是里面的函数若没有调用执行,那么外部的函数不会被销毁。
7. 原生js创建文本节点、元素节点,删除节点,添加文本节点到元素节点:
(1)、var txt = document.createTextNode("text"); //创建文本节点的方法。
(2)、var elem = document.createElement("li"); //创建元素节点 "li"。
(3)、elem.appendChild(txt); //添加文本节点到元素节点的最后子节点上。
(4)、ul.appendChild(elem) ; //在ul里添加li元素节点。
(5)、ul.removeChild(elem); //删除ul中的elem元素节点。
下面是用这些方法实现的添加水果和删除水果的功能的代码:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>dom节点添加删除</title> 6 <style> 7 span{ 8 cursor: pointer; 9 } 10 </style> 11 </head> 12 <body> 13 <input type="text" id="foods"> 14 <input type="button" id="add" value="添加"> 15 <ul id="ul"> 16 <li>苹果 <span class="del">删除</span> </li> 17 <li>香蕉 <span class="del">删除</span> </li> 18 <li>橙子 <span class="del">删除</span> </li> 19 <li>桑葚 <span class="del">删除</span> </li> 20 </ul> 21 <script> 22 var foods = document.getElementById("foods"); 23 var add = document.getElementById("add"); 24 var ul = document.getElementById("ul"); 25 var li = ul.getElementsByTagName("li") 26 add.onclick = function(){ 27 var elemLi = document.createElement("li"); 28 var foodsVal = foods.value; 29 var txt = document.createTextNode(foodsVal); 30 elemLi.appendChild(txt); 31 ul.appendChild(elemLi); 32 var elemSpan = document.createElement("span"); 33 elemSpan.className = "del"; 34 var txtDelete = document.createTextNode(" 删除"); 35 elemSpan.appendChild(txtDelete); 36 elemLi.appendChild(elemSpan); 37 } 38 //下面的删除节点用的是事件委托,可以删除新添加上li。 39 ul.onclick = function(event){ 40 if(event.target.className == "del"){ //event.target就代表在ul的所有子元素下当前点击的元素。 41 ul.removeChild(event.target.parentNode); 42 } 43 }
8. 事件冒泡和时间捕获的问题:
这里就要提到addEventListener()方法,addEventListener()与removeEventListener()用于处理指定和删除事件处理程序操作。所有的DOM节点中都包 含这两种方 法,并且它们都接受3个参数:要处理的时间名、作为事件处理程序的函数和一个布尔值。最后这个布尔值参数是true,表示在捕获阶段调用事件处 理程序;如果是false, 表示在冒泡阶段调用事件处理程序。
addEventListener的参数一共有三个,语法为:
element.addEventListener(type,listener,useCapture)
下面是需要注意的事项:
(1)其中element是要绑定函数的对象。
(2)type是事件名称,要注意的是"onclick"要改为"click","onblur"要改为"blur",也就是说事件名不要带"on"。
(3)listener当然就是绑定的函数了,记住不要跟括号。
(4)最后一个参数是个布尔值,表示该事件的响应顺序。
下面是关于addEventListener的一个小例子:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>事件冒泡</title> 6 <style> 7 #outer,#inner,#con{ 8 margin: 0 auto; 9 padding: 50px 0; 10 } 11 #outer{ 12 height: 250px; 13 width: 300px; 14 background-color: #999; 15 } 16 #con{ 17 height: 150px; 18 width: 200px; 19 background-color: #ccc; 20 } 21 #inner{ 22 height: 50px; 23 width: 100px; 24 background-color: #eee; 25 } 26 </style> 27 </head> 28 <body> 29 <div id="outer"> 30 <div id="con"> 31 <div id="inner"></div> 32 </div> 33 </div> 34 <script> 35 var outer = document.getElementById("outer"); 36 var inner = document.getElementById("inner"); 37 var con = document.getElementById("con"); 38 inner.addEventListener("click",function(){ 39 console.log("inner"); 40 },true) 41 42 outer.addEventListener("click",function(){ 43 console.log("outer"); 44 },true) 45 con.addEventListener("click",function(){ 46 console.log("con"); 47 },true) 48 49
上面这个例子中,如果你点击id为inner的盒子,控制台会输出 outer con inner 以事件捕获的顺序调用程序。如果不用这个方法,只用单纯的点击事件,那么他会按冒泡 顺序调用执行程序。
9.回调函数
定义:将一个函数作为参数传给另一个函数或者方法,常见的setInterval(function(),1000) 就是将function函数传到了setInterval方法中。上面的 addEventListener方法也是回调函数。
下面有个例子
1 function fun(Fun){ //函数名fun 形参是Fun 2 Fun(); //这里调用名为Fun的函数,因为程序走到这里并没有执行,因为在后面调用是才执行。 3 console.log("xixi~"); 4 } 5 fun(function(){ //调用函数fun ,实参为一个函数,这里这个函数就是作为参数传给了fun函数,这时候fun函数执行,Fun()调用函数就可以执行被当作参数的函数了,即控制台会输出haha~。 6 console.log("haha~"); 7 })
下面是用原生JS编写的图片切换按钮背景颜色改变的例子:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>banner_roll_change</title> 6 <style> 7 *{ 8 margin: 0; 9 padding: 0; 10 list-style: none; 11 } 12 div{ 13 margin: 0 auto; 14 width: 30%; 15 height: 300px; 16 position: relative; 17 } 18 div img{ 19 width: 100%; 20 } 21 ul{ 22 position: absolute; 23 left: 50%; 24 margin-left: -60px; 25 } 26 ul li{ 27 float: left; 28 width: 10px; 29 height: 10px; 30 background-color: #999; 31 border-radius: 50%; 32 margin-right: 20px; 33 } 34 /* ul li a{ 35 display: block; 36 }*/ 37 .active{ 38 background-color: red; 39 } 40 </style> 41 </head> 42 <body> 43 <div> 44 <img src="images/5.jpg" id="pic"> 45 </div> 46 <ul> 47 <li class="list"><a href="#"></a></li> 48 <li class="list"><a href="#"></a></li> 49 <li class="list"><a href="#"></a></li> 50 <li class="list"><a href="#"></a></li> 51 </ul> 52 // <script src="jquery-1.11.1.js"></script> 53 <script> 54 55 //用jquery编写点击背景色改变 56 // $("a").click(function(){ 57 // $(this).addClass("active").parent().siblings().find("a").removeClass("active"); 58 // }) 59 60 61 //用原声js 62 63 var lis = document.getElementsByClassName("list"); 64 var pic = document.getElementById("pic"); 65 var picArr = ["images/5.jpg","images/6.jpg","images/7.jpg","images/8.jpg"]; 66 for(var i = 0;i<lis.length;i++){ 67 lis[i].onclick = function(ind){ 68 return function(){ 69 pic.src = picArr[ind]; 70 addClass(this,"active"); 71 var sib = siblings(this); 72 for(var j = 0;j<sib.length;j++){ 73 removeClass(sib[j],"active"); 74 } 75 } 76 }(i) 77 } 78 function addClass(obj,name){ //添加样式函数 79 obj.className = obj.className + " " + name; 80 } 81 function siblings(obj){ //获取到除当前按钮以外其他按钮 82 var sibArr = obj.parentNode.children; 83 var sibNewArr = []; 84 for(var i = 0;i<sibArr.length;i++){ 85 if(sibArr[i] != obj){ 86 sibNewArr.push(sibArr[i]); 87 } 88 } 89 return sibNewArr; 90 } 91 function removeClass(obj,name){ //删除样式函数 92 var classStr = obj.className; 93 var classArr = classStr.split(" "); 94 var classNewArr = []; 95 for(var i = 0;i<classArr.length;i++){ 96 if(classArr[i] != name){ 97 classNewArr.push(classArr[i]); 98 } 99 } 100 obj.className = classNewArr.join(" "); 101 } 102 </script> 103 </body> 104 </html>