元素(element)和节点(node)
childNode属性和children属性的区别
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="parentDiv"> <!--注释--> <div></div> </div> <script> console.log(document.getElementById('parentDiv').childNodes); //NodeList[5] console.log(document.getElementById('parentDiv').children) ; //HTMLCollection[1] </script> </body> </html>
childNodes属性返回的是NodeList数组,是属于节点(也包括元素)的属性,而children属性返回的是子元素,是属于元素的属性
而在Nodelist数组里面也有元素存在,证明了元素也是节点的一种,即元素节点。
W3C中的解释是:
在 HTML DOM (文档对象模型)中,每个部分都是节点 文档本身是文档节点 所有 HTML 元素是元素节点 所有 HTML 属性是属性节点 HTML 元素内的文本是文本节点 (包括回车符,空格,空白字符也是属于文本节点) 注释是注释节点
Element 对象可以拥有类型为元素节点、文本节点、注释节点的子节点。
NodeList 对象表示节点列表,比如 HTML 元素的子节点集合。
元素也可以拥有属性。属性是属性节点。
总结:元素是元素节点,是节点中的一种,但元素节点中可以包含很多的节点
nodeName(纯大写) 属性含有某个节点的名称
元素节点的nodeName 是标签名称 属性节点的nodeName 是属性名称 文本节点的nodeName 永远是 #text 文档节点的nodeName 永远是 #document
nodeValue 对于文本节点,nodeValue 属性包含文本。 对于属性节点,nodeValue 属性包含属性值
nodeValue 属性对于文档节点和元素节点是不可用的
nodeType 属性可返回节点的类型
Element 元素 1 Attribute 属性 2 Text 文本 3 CDATA Section CDATA断 4 Entity Reference 实体参数 5 Entity 实体 6 Processing Instrucion 处理指令 7 Comment 注释 8 Document 文档 9 Document Type 文档类型 10 Document Fragment 文档片断 11
添加和删除节点(HTML 元素)
创建新的 HTML 元素
如需向 HTML DOM 添加新元素,您必须首先创建该元素(元素节点),然后向一个已存在的元素追加该元素
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="div1"> <p id="p1">这是一个段落</p> <p id="p2">这是另一个段落</p> </div> </body> <script> var para=document.createElement("p"); var node=document.createTextNode("这是新段落。"); para.appendChild(node); var element=document.getElementById("div1"); element.appendChild(para); </script> </html> <!-- 为这段代码创建新的 <p> 元素: var para=document.createElement("p"); 此时检查页面可以看到div里面已经生成了<p>元素 如需向 <p> 元素添加文本,您必须首先创建文本节点。 这段代码创建了一个文本节点: var node=document.createTextNode("这是新段落。"); 然后您必须向 <p> 元素追加这个文本节点: para.appendChild(node); 最后您必须向一个已有的元素追加这个新元素。 这段代码找到一个已有的元素: var element=document.getElementById("div1"); 这段代码向这个已有的元素追加新元素: element.appendChild(para); -->
删除已有的 HTML 元素
如需删除 HTML 元素,您必须首先获得该元素的父元素
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="div1"> <p id="p1">这是一个段落。</p> <p id="p2">这是另一个段落。</p> </div> </body> <script> var parent=document.getElementById("div1"); var child=document.getElementById("p1"); parent.removeChild(child); </script> </html> <!-- 例子解释: 这个 HTML 文档含有拥有两个子节点(两个 <p> 元素)的 <div> 元素: <div id="div1"> <p id="p1">这是一个段落。</p> <p id="p2">这是另一个段落。</p> </div> 找到 id="div1" 的元素: var parent=document.getElementById("div1"); 找到 id="p1" 的 <p> 元素: var child=document.getElementById("p1"); 从父元素中删除子元素: parent.removeChild(child); 提示:如果能够在不引用父元素的情况下删除某个元素,就太好了。 不过很遗憾。DOM 需要清楚您需要删除的元素,以及它的父元素。 这是常用的解决方案: 找到您希望删除的子元素,然后使用其 parentNode 属性来找到父元素: var child=document.getElementById("p1"); child.parentNode.removeChild(child); -->
常用节点操作
1.节点查找 document.getElementById,document.getElementByTagName,document.getElementByName ,document.getElementByClassName document.querySelector() 参数为选择器 document.forms 选取页面中的所有表单元素 2.增加节点 增加节点前必须先使用document.createElement()创建元素节点,参数为标签名 m.appendChild(n) 为m元素在末尾添加n节点 m.insertBefore(k,n) 在m元素的k节点前添加n节点 3.删除节点 m.removeChild(n)删除m元素中的n节点 m.replaceChild(k,n)用n节点取代m元素中的k节点 4.复制节点 m.cloneChild() 复制m节点,并将复制出来的节点作为返回值 参数为true时,则将m元素的后代元素也一并复制。否则,仅复制m元素本身 节点属性操作 节点(自身)属性: attributes - 节点(元素)的 属性节点 nodeType – 节点类型 nodeValue – 节点值 nodeName – 节点名称 innerHTML - 节点(元素)的文本值 1.节点属性值选取 m.属性名 (:驼峰形式 ) m.className m[“属性名”] m.['className'] m.getAttribute(“属性名”) :加引号,html的形式 m.getAttribute("class") 2.节点属性修改 前两种选取方法时,直接赋值即可 m.setAttribute("属性名",“值”) 3.创建属性节点并设置属性值 var info_node=document.createAttribute("info");//创建 info_node.value='123';//设置 sup1.setAttributeNode(info_node);//添加 4.复制节点 var body = document.querySelector('body'); true深拷贝,拷贝自身与内容, false浅拷贝,只拷贝自身标签 var cl_body = body.cloneNode(true); console.log(cl_body); JS DOM节点(当前标签和同级、父级、子级..之间的关系) 1. 通过顶层document节点获取 1) document.getElementById(elementId) //根据id获得 2) document.getElementsByName(elementName) //根据name获得 3) document.getElementsByTagName(tagName) //根据标签名获得 2、通过父节点获取 1) parentObj.firstChild //获得第一个子节点 2) parentObj.lastChild //获得第二个子节点 3) parentObj.childNodes //获取作为指定对象直接后代的HTML元素和TextNode对象的集合 4) parentObj.children //非标准dom集合,建议使用childNodes 5) parentObj.getElementsByTagName(tagName) //获得该标签下标签名为tagName的所有标签 3、通过临近节点获取 1) neighbourNode.previousSibling //获得同级前一个标签 2) neighbourNode.nextSibling //获得同级后一个标签 4、通过子节点获取 1) childNode.parentNode //获得父标签
事件
onload:页面加载完毕事件,只附属于window对象 onclick:鼠标点击时间 onmouseover:鼠标悬浮事件 onmouseout:鼠标移开事件
on事件绑定方式
document.onclick = function() { console.log("文档点击"); }
on事件只能绑定一个方法,重复绑定保留最后一次绑定的方法
document.onclick = function() { console.log("文档点击"); }
事件的移除
document.onclick = null;
非on事件绑定方式
document.addEventListener('click', function() { console.log("点击1"); })
document.addEventListener('click', function() { console.log("点击2"); })
非on事件可以同时绑定多个方法,被绑定的方法依次被执行
addEventListener第三个参数(true|false)决定冒泡的方式
function fn () {} document.addEventListener('click', fn);
事件的移除
document.removeEventListener('click', fn,false);
事件的三种绑定方式的思考
方法一:嵌入dom 把onclick绑定在标签上 HTML元素行间事件(也可以叫HTMl事件处理程序),直接在html标签里添加事件。 缺点:html和js代码紧密耦合 <input id="btn1" type="button" onclick="test();" /> 方法二:直接绑定 onclick的js绑定办法 //把一个函数赋值给一个事件处理程序属性。(这种方式也叫做Dom0级事件处理程序) var btn1 = document.getElementById('btn1'); function abc() { alert('abc'); } btn1.onclick = abc; //当点击的时候执行abc这个函数,等价于 btn1.onclick=function abc(){alert('abc');} //btn1.onclick = null; //去掉绑定的事件 方法三:事件监听 click的js绑定办法(js的话推荐这种) //通过“事件监听”的方式来绑定事件(也叫Dom2级事件处理程序) var btn2 = document.getElementById('btn2'); btn2.addEventListener('click', showMsg, false); //鼠标单击的时候调用showMes这个函数 function showMsg() { alert("事件监听"); } //btn2.removeEventListener('click', showMsg, false); //去除绑定 方法一 最原始的写法:和html混合在一起写,缺点是代码高冗余,且无法添加多个事件处理函数如上文对事件的举例则为典型的**html事件处理程序*写法 方法二 dom0级:将html代码和js代码分离,且支持匿名函数,可以看到完美的改进了1的冗余缺憾,所有的事件相关操作都在js中完成 方法三 dom2级:ie使用attachEventListener其他非ie使用addEventListener,可以支持绑定多个事件,瞧吧,又一个缺憾被完美解决了~,而且dom2级还可以自定义事件流,下一篇会分析事件流模型 dom3级:对事件进行了更广而全的分类,请自行查阅
实例运用一
</head> <body> <div class="div"></div> <div class="div"></div> </body> <script> // js事件: 页面标签在满足某种条件下可以完成指定功能的这种过程, 成之为事件 // 某种条件: 如鼠标点击标签: 点击事件 | 鼠标双击标签: 双击事件 | 键盘按下: 键盘按下事件 // 指定功能: 就是开发者根据实际需求完整相应的功能实现 // 钩子函数: 就是满足某种条件被系统回调的函数(完成指定功能) // 点击事件: 明确激活钩子的条件 = 激活钩子后改处理什么逻辑, 完成指定功能(函数) var div = document.querySelector(".div"); // 找到的是第一个.div div.onclick = function () { // alert(123) this.style.backgroundColor = "pink"; } // 明确第一个及第二个 var divs = document.querySelectorAll('.div'); divs[1].ondblclick = function () { divs[0].style.backgroundColor = "yellow"; } </script> </html>
实例运用二
复习并延伸 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>复习预习</title> <style> [key='value'] { color: #0f8209; } </style> </head> <body> <div class="ele" alert="OK">div div div</div> </body> <script> // 1.面向对象js // ES5 // 普通的单一对象 var obj = { // 普通对象的属性 key: "value", fn: function () { console.log("普通对象的方法") } }; console.log(obj.key); console.log(obj["key"]); // 1.key的类型为字符串类型 // 结论: // js支持的标识符可以省略引号, 反之不可以省略 // 不支持的标识符访问方式: 不可以采用.语法,需要采用[]语法,eg:obj["background-color"] var obj1 = { "name": "obj1", // key有时候会出现js不能直接支持的标识符书写方式 // 需求: obj1用来描述页面标签的各种颜色 color: "red", // "color": "red", "background-color": "yellow" } console.log(obj1.name); console.log(obj1["name"]); console.log(obj1.color); // obj1.background = 12; // color = 10; console.log(obj1["background-color"]); // 2. 对象可以任意添加或删除属性 var obj2 = { name: "obj2" }; console.log(obj2); // 删除属性 delete obj2.name; console.log(obj2); // 添加属性 obj2.age = 8; console.log(obj2); // 拓展: 获取的页面元素就是标签对象, 可以对其添加任意属性 var ele = document.querySelector('.ele'); console.log(ele.info); // 直接使用无值, 原因ele并没有添加该属性 ele.info = "添加的属性信息"; // 添加属性 console.log(ele.info); // 添加属性后就可以正常方式添加的属性值 delete ele.info; // 删除操作 console.log(ele.info); // 删除后属性又会消失 // 构造函数 function Perple(name, age) { this.name = name; this.age = age; this.fn = function () { console.log("fn") } } // 实例化对象 var p = new Perple("张三", 18); p.fn(); // ES6 class Student { constructor (name, age) { this.name = name; this.age = age; } fn () { console.log("fn") } } var s = new Student("张三", 18); s.fn(); </script> <script> // getElementById只能由document调用 var ele = document.getElementsByClassName("ele")[0]; console.log(ele); ele = document.querySelector(".ele"); console.log(ele); ele = document.querySelectorAll(".ele")[0]; console.log(ele); // 该添加属性的方式只映射到js代码中 ele.index = 123; console.log(ele.index); // js如何操作元素(页面标签)的全局属性, 映射到html代码中 ele = document.querySelector('[alert]'); // 通过全局属性获取元素 console.log(ele); // 获取全局属性值 var info = ele.getAttribute('alert'); console.log(info); // 修改全局属性值 ele.setAttribute('alert', 'no ok'); // 添加全局属性值(映射到html代码中) => 结合CSS来控制页面标签的样式 ele.setAttribute('key', 'value'); </script> </html>
事件参数event
存放事件信息的回调参数
在触发DOM上某个事件时,会产生一个事件对象event,这个对象包含着所有事件有关的信息(导致事件的元素、事件的类型、与特定事件相关的信息)
所有浏览器都支持Event对象,但支持方式不同
IE中的事件对象:window.event
阻止事件冒泡 DOM中提供stopPropagation()方法,但IE不支持,使用event对象在事件函数中调用就行 IE中提供的是,cancelBubble属性,默认为false,当它设置为true时,就是阻止事件冒泡,也是用event对象在事件函数中调用 jQuery中提供了stopPropagation()方法来停止事件冒泡,当需要时,只需用用event对象来调用就行,即event.stopPropagation(); 默认行为 阻止默认行为 DOM中提供preventDefault()方法来取消事件默认行为,但是只有当cancelable属性设置为true的事件,才可以使用preventDefault()来取消事件默认行为,使用event对象在事件函数中调用就行 IE中提供的是returnValue属性,默认为true,当它设置为false时,就是取消事件默认行为,也是用event对象在事件函数中调用 jQuery中提供了preventDefault()方法来阻止元素的默认行为,只需要用event对象来调用就好,即event.preventDefault() 如果想同时对事件对象停止冒泡和默认行为,可以在事件处理函数中返回false。这是对事件对象同时调用stopPropagation()方法和preventDefault()方法的一种简写方式
事件注意点
1、event代表事件的状态,例如触发event对象的元素、鼠标的位置及状态、按下的键等等; 2、event对象只在事件发生的过程中才有效。 firefox里的event跟IE里的不同,IE里的是全局变量,随时可用; firefox里的要用参数引导才能用,是运行时的临时变量 在IE/Opera中是window.event,在Firefox中是event; 而事件的对象,在IE中是window.event.srcElement,在Firefox中是event.target,Opera中两者都可用
处理冒泡与默认事件
事件的冒泡:父子都具有点击事件,不处理的话,点击子级也会出发父级的点击事件
如果提供了事件对象,则这是一个非IE浏览器 if ( e && e.stopPropagation ) 因此它支持W3C的stopPropagation()方法 e.stopPropagation(); else 否则,我们需要使用IE的方式来取消事件冒泡
window.event.cancelBubble = true;
return false;
处理冒泡实例
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>事件对象</title> <style> body { margin: 0; } .box { background-color: pink; } .sup { 200px; height: 200px; background-color: red; } .sub { 100px; height: 100px; background-color: orange; } </style> </head> <body> <div class="box">12345</div> <div class="sup"> <div class="sub"></div> </div> <a href="https://www.baidu.com">只想相应点击事件</a> </body> <script> var box = document.querySelector('.box'); // 事件的钩子函数, 系统回调时传递了一个值, 该值为事件对象 box.onclick = function (ev) { // 回调函数 console.log(ev) // 特殊按键 altKey | shiftKey | ctrlKey console.log(ev.altKey) // 鼠标的点击点 console.log(ev.clientX, ev.clientY) } </script> <script> var sup = document.querySelector('.sup'); var sub = document.querySelector('.sub'); // 事件默认有冒泡, 子级相应事件后,会将事件传递给父级,如果父级有相同事件,也会被激活, 最终传递给document sub.onclick = function (ev) { console.log(ev); // 取消冒泡, 当自身处理事件后, 该事件就处理完毕, 结束, 不再向上传递 ev.cancelBubble = true; console.log("子级被点击了") }; sup.onclick = function () { console.log("父级被点击了") }; document.onclick = function () { console.log("文档被点击了") } </script> </html>
事件默认行为:当一个事件发生时浏览器自己会做的事情
如果提供了事件对象,则这是一个非IE浏览器 if ( e && e.preventDefault ) 阻止默认浏览器动作(W3C) e.preventDefault(); else IE中阻止函数器默认动作的方式 window.event.returnValue = false; return false; 既然return false 和 e.preventDefault()都是一样的效果,那它们有区别吗?当然有 仅仅是在HTML事件属性 和 DOM0级事件处理方法中 才能通过返回 return false 的形式组织事件宿主的默认行为
处理默认事件实例
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>事件对象</title> <style> body { margin: 0; } .box { background-color: pink; } .sup { 200px; height: 200px; background-color: red; } .sub { 100px; height: 100px; background-color: orange; } </style> </head> <body> <div class="box">12345</div> <div class="sup"> <div class="sub"></div> </div> <a href="https://www.baidu.com">只想相应点击事件</a> </body> <script> var box = document.querySelector('.box'); // 事件的钩子函数, 系统回调时传递了一个值, 该值为事件对象 box.onclick = function (ev) { // 回调函数 console.log(ev) // 特殊按键 altKey | shiftKey | ctrlKey console.log(ev.altKey) // 鼠标的点击点 console.log(ev.clientX, ev.clientY) } </script> <script> // 默认事件 var aBtn = document.querySelector('a'); aBtn.onclick = function (ev) { ev.cancelBubble = true; console.log("a被点击了"); // 手动转跳页面 open('https://www.oldboyedu.com', '_self'); // a标签默认会完成转跳, 如果取消默认事件 return false; } </script> </html>
再补充一些
默认操作 具体指的是什么呢?
(1)把单击事件处理程序注册到一个锚元素,而不是一个外层的<div>上,那么就要面对另外一个问题:当用户单击链接时,浏览器会加载一个新页面。
(2)当用户在编辑完表单后按下回车键时,会触发表单的submit事件,在此事件发生后,表单提交才会真正发生。
这种行为与我们讨论的事件处理程序不是同一个概念,它是单击标签元素的默认操作。
如果我们不希望执行这种默认操作,那么在事件对象上调用.stopPropagation()方法也无济于事,因为默认操作不是在正常的事件传播流中发生的
在这种情况下,处理方法有:
1、w3c的方法是e.preventDefault(),IE则是使用e.returnValue = false; preventDefault它是事件对象(Event)的一个方法,作用是取消一个目标元素的默认行为。既然是说默认行为,当然是元素必须有默认行为才能被取消,如果元素本身就没有默认行为,调用当然就无效了。什么元素有默认行为呢?如链接<a>,提交按钮<input type=”submit”>等。当Event 对象的 cancelable为false时,表示没有默认行为,这时即使有默认行为,调用preventDefault也是不会起作用的。 1 <a href="http://www.cnblogs.com/yycode/" id="testA" >caibaojian.com</a> var a = document.getElementById("testA"); a.onclick =function(e){ if(e.preventDefault){ e.preventDefault();// }else{ window.event.returnValue = false;//IE //注意:这个地方是无法用return false代替的 //return false只能取消元素 } } 2、return false; javascript的return false只会阻止默认行为,而是用jQuery的话则既阻止默认行为又防止对象冒泡
常见事件
鼠标事件
var box = document.querySelector('.box'); 1. 点击事件 box.onclick = function () { console.log("单击"); }; 2. 双击事件(应用场景不广) box.ondblclick = function () { console.log("双击"); }; 3. 鼠标右键 box.oncontextmenu = function () { console.log("右键了"); return false; }; 4. 鼠标悬浮 | 移动 | 按下 | 抬起 | 离开 box.onmouseover = function () { console.log("悬浮"); }; box.onmousemove = function () { console.log("移动"); }; box.onmousedown = function () { console.log("按下"); }; box.onmouseup = function () { console.log("抬起"); }; box.onmouseout = function () { console.log("离开"); } 事件参数ev ev.clientX:点击点X坐标 ev.clientY:点击点Y坐标
over | out VS enter | leave
总结: 1. 将子级与父级分开考虑, 大家都有各自的悬浮离开事件, 采用 over | out 组合 2. 将子级纳入父级考虑范围, 也就是只有父级去相应悬浮离开事件, 采用 enter | leave 组合 3. 单独考虑一个盒子的悬浮离开事件, 两套均可以 特性 从父级移至子级, 会触发out事件, 紧接着触发子级的over事件, 并可以冒泡给父级 从父级移至子级, leave事件并不会触发, 它认为子级是属于父级的一部分, enter事件, 也不会再次触发 悬浮子级: sub over => sup over 支持冒泡 sup enter => sub enter 不支持冒泡
键盘事件
键盘事件 onkeydown:键盘按下会触发,长按持续触发 onkeyup:键盘抬起 事件参数ev ev.keyCode:按键编号 ev.altKey:alt特殊按键 ev.ctrlKey:ctrl特殊按键 ev.shiftKey:shift特殊按键 <head> <meta charset="UTF-8"> <title>键盘事件</title> <style> .box { 100px; height: 100px; background: orange; position: absolute; top: 0; left: 0; } </style> </head> <body> <div class="box"></div> </body> <script> // 键盘长按会一直触发按下事件 document.onkeydown = function (ev) { console.log(ev); // 按下的键盘编号 console.log("按下", ev.keyCode); // console.log(ev.which); } document.onkeyup = function (ev) { console.log("抬起", ev.keyCode); } // 左上右下: 37-40 var box = document.querySelector('.box'); document.onkeydown = function (ev) { switch (ev.keyCode) { case 37: box.style.left = box.offsetLeft - 10 + 'px'; break; case 38: box.style.top = box.offsetTop - 10 + 'px'; break; case 39: box.style.left = box.offsetLeft + 10 + 'px'; break; case 40: box.style.top = box.offsetTop + 10 + 'px'; break; } } </script> </html>
表单事件
onfocus:获取焦点 onblur:失去焦点 onselect:文本被选中 oninput:值改变 onchange:值改变,且需要在失去焦点后才能触发 onsubmit:表单默认提交事件
文档事件
文档事件由window调用 onload:页面加载完毕触发 onbeforeunload:页面退出或刷新警告,需要设置回调函数返回值,返回值随意
图片事件
onerror:图片加载失败
页面事件
onscroll:页面滚动 onresize:页面尺寸调整 window.scrollY:页面下滚距离
文档页面事件运用实例
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>其他事件</title> <script> // 当页面加载完毕之后再回调 window.onload = function () { var box = document.querySelector('.box'); console.log(box); } // 页面滚动可以设置给 window | document var isShow = false; window.onscroll = function () { console.log(window.scrollY); if (window.scrollY >= 1200) { if (!isShow) { console.log("将返回Top按钮显示"); isShow = true; } } else { if (isShow) { isShow = false; } } } </script> </head> <body> <div class="box"></div> <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br> </body> </html>
JS选择器
getElement系列
通过id名获取唯一满足条件的页面元素
document.getElementById('id名'); 该方法只能由document调用 任何HTML元素可以有一个id属性,在文档中该值必须唯一 若浏览器中出现多个id名的情况,CSS样式对所有该id名的元素都生效,但javascript脚本仅对第一个出现该id名的元素生效。 getElementById()该方法接收一个参数:要取得元素的id,若找到则返回该元素,若不存在则返回null 注意:document.getElementById方法的内部实现需要用到this,这个this本来被期望指向document 跨浏览器兼容 1:在ie7中,使用getElementById()的时候,接收的参数id不区分大小写。 2:在表单元素中,如果表单设置有name属性,其name属性会被当做id识别出来。 3:id是唯一的,但name属性并不是唯一的。具有该名称的隐式全局变量会引用一个类数组对象,包括所有该命名的元素
通过class名获取所有满足条件的页面元素
document.getElementsByClassName('class名'); 该方法可以由document及任意页面元素对象调用 document.getElementsByClass("class1 class2")可以拿到同时拥有class1和class2的元素,中间用空格隔开,不区分class1和class2的顺序。 兼容性:IE8及其以下版本的浏览器未实现getElementsByClassName方法 返回值为HTMLCollection (一个类数组结果的对象,使用方式同数组) 没有匹配到任何结果返回空HTMLCollection对象 ([])
通过name属性获取元素
getElementsByName(返回值是一个nodeList集合(区别于Array),可作用于Dom元素) getElementsByName()方法接收一个参数,即要取得元素的name值。 document.getElementsByName("Name");Name为要获取元素的name属性值,这个方法一般适用于提交表单数据,当 元素为form、img、iframe、applet、embed、object的时候设置name属性时,会自动在Document对象中创建以该 name属性值命名的属性。 所以可以通过document.domName引用相应的dom对象。 在ie9中,getElementsByName()只对表单元素起作用。 IE9-浏览器中使用getElementsByName()方法也会返回id属性匹配的元素。因此,不要将name和id属性设置为相同的值。
通过tag名获取所有满足条件的页面元素
document.getElementsByTagName('tag名'); 该方法可以由document及任意页面元素对象调用 返回值为HTMLCollection (一个类数组结果的对象,使用方式同数组) 没有匹配到任何结果返回空HTMLCollection对象 ([]) 可以使用方括号语法或item()方法来访问类数组对象中的项,length属性表示对象中元素的数量。 [注意]通过getElementsByTagName()方法取得的类数组对象有一个namedItem()方法,可以通过元素的name属性取得集合中的第一个值。safari和IE不支持该方法。document.getElementsByTagName("*")表示匹配文档的所有元素
querySelect系列
获取第一个匹配到的页面元素
document.querySelector('css语法选择器'); 该方法可以由document及任意页面对象调用
获取所有匹配到的页面元素
document.querySelectorAll('css语法选择器'); 该方法可以由document及任意页面对象调用 返回值为NodeList (一个类数组结果的对象,使用方式同数组) 没有匹配到任何结果返回空NodeList对象 ([])
id名
可以通过id名直接获取对应的页面元素对象,但是不建议使用
js选择器运用实例
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>js选择器</title> <style> #d { color: red; } </style> </head> <body id="bd"> <!--注释--> <div id="d" class="dd">我是ddd111</div> <div id="d" class="dd">我是ddd222</div> <div class="sup1"> <div id="div"></div> </div> <div class="sup2"> <div id="div"></div> </div> </body> <script> // 节点(了解): 在文档(document)中出现的所有内容都是document中的节点 // 节点(node): 标签节点(元素element) | 注释节点 | 文本节点 | <!doctype>节点 console.log([bd]) // 文本 注释 文本 标签 文本 标签 文本 标签 文本 标签 文本 </script> <script> // js选择器: 将js与html建立起连接 // js中一般称标签为页面元素 // 1.直接通过id名进行匹配 console.log(d); // 两个都可以找到 // 2.getElement系列(最严谨) // 所有显示在页面中的内容(展现给用户看的), 都是属于文档(document)对象的内容, 存放在文档中 // console.log(document) // 获取文档中的标签 => document对象通过.语法去获取具体的目标标签元素 // ① id var div = document.getElementById('d'); // 检索得到页面中出现的第一个满足条件的目标 console.log(">>>", div); var body = document.getElementById("bd"); console.log(body); // 注: getElementById该方法只能由document来调用 // 原因: 我们需要保证一个文档中一个id只能出现一次, document检索的就是文档, // 而某父级标签只能检索自身标签内部区域, document可以保证文档中只能一个id // 只出现一次,某父级标签只能保证自身内部区域id不重复,能不能保证与外界不重复? // 不能, 所以从安全角度出发, 获取唯一对象的getElementById方法只能由能确定唯一id的 // 对象来调用, 能被document调用, 不能被sup来调用 // ② 类名 var divs = document.getElementsByClassName('dd'); console.log(divs); // 两个div在body之中, 上方已经获取了body, 那能否通过body来获取body中的div var divs1 = body.getElementsByClassName('dd'); console.log(divs1); // ③ 标签名 var divs = document.getElementsByTagName('div'); console.log(divs) console.log('--------------------------------------------------'); // 3.querySelector系列(最方便) // 参数: 就是css选择器语法 // querySelector检索第一个 var div = document.querySelector('body > .dd'); console.log(div); // querySelectorAll检索所有满足结果 var divs = document.querySelectorAll('body > .dd'); console.log(divs); var divs = body.querySelectorAll('.dd'); console.log(divs) var divs = body.querySelectorAll('#d'); // 不严谨 console.log(divs) </script> </html>
选择器分类
1. ID选择器 使用ID选择器时,需在前面添加“#”,区分大小写,语法如下:document.querySelector('#id'); //等同于document.getElementById('id') 2. 元素选择器 元素选择器通过指定的标签查询元素,此时querySelectorAll等同于getElementsByTagName,语法如下:document.querySelectorAll('a'); //获取页面上的所有a元素并返回元素 3. 样式类选择器 使用元素的样式类获取一个或一类元素,样式名字前使用“.”(英文句号)开头,语法如下:document.querySelectorAll('.btn'); //获取所有样式类中包含btn类名的元素 4. 分组选择器 使用querySelectorAll不仅可以获取一个或一类元素,还可以同时获取其他类别元素,两种类型之间使用逗号隔开,语法如下:document.querySelectorAll('a,p'); //获取页面上所有a元素和p元素,并通过一个列表返回document.querySelectorAll('.btn,.txt'); //获取页面上所有包含btn和txt样式类名的元素 5. 属性选择器 获取页面上包含指定属性的元素,属性名称可以是元素原生属性和用户自定义属性,语法如下:document.querySelectorAll('a[target="_blank"]'); //获取页面上所有target属性为_blank的a元素document.querySelectorAll('img[data-id]'); //获取页面上所有带有自定义属性data-id的img元素 6. 后代选择器 主要用于选择作为某元素后代的元素,规则左边的选择器一端包含两个或多个用空格分隔的选择器,如div a可以理解为查找所有被div包围的所有a元素,语法如下:document.querySelectorAll('div a'); //获取页面上所有被div包含的a元素document.querySelectorAll('div .btn'); //获取页面上所有被div包含的带有btn样式类名的元素 7. 子元素选择器 后代选择器会将元素底下的所有相关元素都搜索出来,如果想进一步缩小范围,可以使用子元素选择器,只会选择某个元素的一级子元素,子元素用“>”(大于号)表示,代码如下: <html> <div id="first"> <div></div> <div></div> </div></html> <script> document.querySelectorAll('html>div'); //只返回一个id为first的div元素</script> 8. 相邻兄弟选择器(比较少用) 选择紧接在另一个元素后的元素,而且两者有相同的父元素,相邻兄弟选择器使用“+”(加号),代码如下: <div> <div></div> <div></div></div><p id="p1"></p><p id="p2"></p><script> document.querySelectorAll('div+p'); //只返回一个id为p1的p元素</script> 9. 伪类选择器 “:first-child”表示选择元素的第一个子元素,“:last-child”表示选择元素的最后一个子元素,“:nth-child(n)”表示选择元素的第n个子元素。“:first-child”的使用例子,代码如下: <div> <p id="p1"></p> <p id="p2"></p></div> <script> document.querySelectorAll('p:first-child'); //只返回一个id为p1的p元素</script>
闭包
function outer() { var data = {} function inner() { return data; } return inner; }
闭包目的:不允许提升变量作用域时,该函数的局部变量需要被其他函数使用
闭包本质:函数的嵌套,内层函数称之为闭包
闭包的解决案例:①影响局部变量的生命周期,持久化局部变量;②解决变量污染
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>闭包</title> </head> <body> 闭包 </body> <script> // 了解知识点 // 闭包: 局部的函数(被一个函数包裹的函数) // 为什么使用闭包: // 1.一个函数要使用另一个函数的局部变量 // 2.闭包会持久化包裹自身的函数的局部变量 // 3.解决循环绑定 // 函数的嵌套定义 function outer() { var num = 10; function inner() { // 1.在inner函数中,使用了outer的局部变量num return num; } return inner; } var innerFn = outer(); // 2.借助闭包,将局部变量num的生命周期提升了 var num = innerFn(); console.log(num); </script> </html>
循环绑定
.html文件
<ul> <li>列表项</li> <li>列表项</li> <li>列表项</li> </ul>
.js文件
var lis = document.querySelector('li'); for (var i = 0; i < lis.length; i++) { lis[i].onclick = function () { // 打印列表项的索引 console.log(i); } }
会发生变量污染
解决方法
1 获取局部作用域解决 2 闭包解决 3 对象属性解决
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>循环绑定</title> </head> <body> <div class="box">0000000000000000001</div> <div class="box">0000000000000000002</div> <div class="box">0000000000000000003</div> </body> <script> var divs = document.querySelectorAll(".box"); /* 存在污染 for (var i = 0; i < divs.length; i++) { // i = 0 | 1 | 2 | 3 // 循环绑定 divs[i].onclick = function () { console.log("***", i) } } // i = 3 console.log(">>>", i); */ /* 利用块级作用域解决 for (let i = 0; i < divs.length; i++) { // {i=0 <= i} {i=1 <= i} {i=2 <= i} // i = 3 // 循环绑定 divs[i].onclick = function () { console.log("***", i) } } // for运行结束, i=3会被销毁 console.log(">>>", i) */ // 利用标签的属性解决 /* for (var i = 0; i < divs.length; i++) { divs[i].index = i; divs[i].onclick = function () { // console.log("###", i) console.log(this.index) } } */ // 利用闭包处理循环绑定 for (var i = 0; i < divs.length; i++) { (function () { var index = i; divs[index].onclick = function () { console.log("###", index) } })() /* (function (index) { divs[index].onclick = function () { console.log("###", index) } })(i) */ /* (function (i) { divs[i].onclick = function () { console.log("###", i) } })(i) */ } </script> </html>
面向对象JS
属性与方法
var obj = {}; | var obj = new Object();
属性
obj.prop = "";
方法
obj.func = function () {}
删除属性与方法
delete obj.prop delete obj.func
属性和方法实际使用
对象: 特征与行为的结合体, 是一个具象的实体 // js对象语法 var obj = { // 属性 name: 'Zero', // 方法 teach: function () { console.log("教学"); } }; // 对象使用属性与方法, 采用.语法 console.log(obj.name); obj.teach();
JS中中括号([ ])与 .
中括号运算符总是能代替点运算符。但点运算符却不一定能全部代替中括号运算符 中括号运算符可以用字符串变量的内容作为属性名。点运算符不能 中括号运算符可以用纯数字为属性名。点运算符不能 中括号运算符可以用js的关键字和保留字作为属性名。点运算符不能
下面的例子中,a.b表示对象a的属性b,既可以设置也可以读取
object[key]=>key为常量时,object[key]等价于object.key,例如:a.b == a['b']
特殊的,object[key] 中key为变量时,只能用中括号形式
var a = {}; // a.b = 1; a['b'] = 1; c = a.b; // c = a['b']; alert(c);
标识符是否合法对两种用法的影响
var obj = {}; // 为obj添加一个属性name,name是合法的标识符,即也可以通过obj.name方式来定义 obj['name'] = 'jack'; // 为obj添加一个属性2a,2a不是合法的标识符(不能以数字开头),不能通过obj.2a来定义 obj['2a'] = 'test'; var obj = {name:'jack'}; obj['2a'] = 'test'; obj['name']; // --> jack obj['2a']; // --> test (不能通过obj.2a获取)
总结:常量用点,变量就用中括号
运算符左侧应当是一个表达式,它返回一个对象。
对于点(.)来说,右侧必须是一个以属性名称命名的简单标识符。
对于方括号([])来说,方括号里必须是一个计算结果为字符串的表达式,这个字符串就是属性的名字
当通过点运算符(.)方法对象属性时,属性名用一个标识符来表示。标识符必须直接出现在js程序中,它们不是数据类型,因此程序无法修改它们。
反过来讲,当通过[]来方式对象的属性时,属性名通过字符串表示。字符串是js的数据类型,在程序运行时可以修改和创建它们
<script type="text/javascript"> var addr = ""; for(i=0;i<4;i++){ addr += cutomer["address" + i] + " "; } </script>
这段代码读取customer对象的address0,adddress1,address2,adddress3属性,并将他们连接起来
类字典结构使用
结构
var dict = {name: "zero", age: 18}
拓展
var dict = {"my-name": "zero", fn: function () {}, fun () {}}
使用
dict.name | dict["my-name"] | dict.fn()
构造函数(ES5)
// 构造函数: 声明与普通函数一样, 只是函数名采用大驼峰命名规则 function Person(name) { // 类似于python中的类一样来使用 // 构造函数内部属性方式不同于普通函数 this.name = name; // this代表Person构造函数实例化出的所有具体对象中的某一个 this.teach = function () { console.log(this.name + "正在教学"); } } // 如何使用构造函数中的属性与方法 // 1. 通过构造函数实例化出具体对象 // 2. 通过对象.语法调用属性与方法 var p1 = new Person("杨虎虎"); // name: 杨虎虎 var p2 = new Person("刘xx"); // name: 刘xx console.log(p1.name); console.log(p2.name); p1.teach(); p2.teach(); 为什么要用new? new 会创建 pre 的对象, 但是没有 new 的话就没有没有可返回的值或对象了,所以是 undefined。 如果不想new 新的对象的话,可以在 pre 的方法里 返回一个值或对象。 function pre(){ this.radius = Math.random(); return this.radius; } 加 new 会把这个函数当作是一个构造器,返回一个对象。 不加的话,就是调用一个普通的函数,结果视函数返回值而定。 有new,就返回对象,不管函数返回值如何。 无new,就看函数返回值。 构造函数最好返回 this 或者无返回值, 否则容易混淆。
类及继承(ES6)
// ES6 // 引入了类 class Student { // 类, 可以实例化对象, 但实例化出的对象需要加以区分 // 需要构造器(构造函数)来完成对象的声明与初始化 // ES6规定方法的语法 constructor (name) { // 属性在构造器中声明并完成初始化 this.name = name; } // 类中规定普通方法 study () { console.log(this.name + "正在学习"); } // 类方法 static fn() { console.log("我是类方法") } } // 1.实例化类的对象 let stu1 = new Student("嘿嘿"); // 2.使用属性与方法 console.log(stu1.name); stu1.study(); let stu2 = new Student("嘻嘻"); console.log(stu2.name); stu2.study(); Student.fn() <script> // 类方法 class Tool { // 功能类(工具类)中的方法都定义为类方法 static max (num1, num2) { return num1 > num2 ? num1 : num2; } } // 通过Tool类来求两个数中的大值, 需要Tool类的对象出现吗? 不需要 => 功能有类直接使用 console.log(Tool.max(666, 888)); // throw "自定义异常"; // console.log("上面如果出现了异常, 逻辑将会被强制停止"); // var num = 10 / 0; // console.log(num) </script>