JavaScriptDOM
DOM:Document Object Model(文本对象模型)
——D:文档-html文档或xml文档
——O:对象-document对象的属性和方法
——M:模型
——DOM是针对xml(html)的基于树的api
——DOM树:节点(node)的层次
——DOM把一个文档表示为一棵家谱树(父、子、兄弟)
——DOM定义了Node的接口以及许多种节点类型来标识xml节点的多个方面。
1.节点及其类型:
1)元素节点
2)属性节点:元素的属性,可以直接通过属性的方式来操作。
3)文本节点:是元素节点的子节点,其内容为文本。
第一个helloworld文档
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript"> //1.当整个HTML文档完全加载成功后触发window.onload事件。 //事件触发时,执行后面function里面的函数体 window.onload = function () { //2.获取所有的button节点,并取得第一个元素 var click = document.getElementsByTagName("button")[0]; //3.为button的onclick事件赋值:当点击button时,执行函数体。 click.onclick = function () { //4.弹出警告框helloworld alert("helloworld"); } } </script> </head> <body> <button>Click</button> </body> </html>
2.JS代码写在哪里
(1)
<!--HTML代码和js代码耦合在一起--> <button onclick="alert('helloworld');">Click</button>
(2)
<body> <button>Click</button> </body> </html> <!-- 在整个HTML文档被加载后,获取其中的节点, 把script节点放在html文档的最后 但不符合些JS代码的习惯 --> <script type="text/javascript"> //1.获取button var btns = document.getElementsByTagName("button"); alert(btms.length); //2.为button添加onclick事件 btns[0].onclick = function () { alert("helloworld"); } </script>
(3)标准
<script type="text/javascript"> //window.onload事件在整个html文档被完全加载后出发执行。 //所以在其中可以获取到html文档的任何元素 window.onload = function () { } </script> </head> <body> <button>Click</button> </body>
3.如何获取元素节点:
1)document.getElementById:根据id属性获取对应的单个节点
2)document.getElementsByTagName:根据标签名获取指定的节点名
3)document.getElementsByName:根据节点的name属性获取符合条件的节点数组
4.获取属性节点:
1)可以直接通过cityNode.id这样的方式获取和设置属性节点的值
2)通过元素节点的getAttributeNode方法来获取属性节点,然后再通过nodeValue来读写
<script type="text/javascript"> //window.onload事件在整个html文档被完全加载后出发执行。 //所以在其中可以获取到html文档的任何元素 window.onload = function () { //1.获取#city节点的所有子节点 var cityNode = document.getElementById("city"); //2.利用元素节点的childNodes方法可以获取指定元素节点的所有子节点 //但该方法不实用,包含文本节点(空白的部分) alert(cityNode.childNodes.length); //3.获取#city节点的所以li子节点(实用) var cityLiNodes = cityNode.getElementsByTagName("li"); alert(cityLiNodes.length); //4.获取指定节点的第一个子节点和最后一个子节点(实用) alert(cityNode.firstChild); alert(cityNode.lastChild); } </script>
5.获取元素节点的子节点
1)childNodes属性获取全部的子节点
2)firstChild属性获取第一个子节点
3)lastChild属性获取最后一个子节点
6.获取文本节点:
1)步骤:元素节点-->获取元素节点的子节点
2)若元素节点只有文本节点一个子节点
例如:
<li id="bj" name="BeiJing"> 北京</li>
可以先获取到指定的元素节点eleNode,
然后利用eleNode.firstChild.nodeValue的方法来读写其文本节点的值
window.onload = function () { //文本节点一定是元素节点的子节点 //1.获取文本节点所在的元素节点 var bjNode = document.getElementById("bj"); //2.通过firstChild定义到文本节点 var bjTextNode = bjNode.firstChild; //3.通过操作文本节点的nodeValue属性来读写文本节点的值 alert(bjTextNode.nodeValue); bjTextNode.nodeValue = "尚硅谷"; }
window.onload = function () { var cityLi = document.getElementsByTagName("li"); for (var i =0;i<cityLi.length;i++){ cityLi[i].onclick = function () { alert(i);//8 } } }
7..节点的属性:
1)nodeName:代表当前节点的名字,只读属性。如果给定节点是一个文本节点,nodeName
2)nodeType:返回一个整数,这个数值代表着给定节点的类型,只读属性。
3)nodeValue:返回给定节点的当前值(字符串),可读写的属性
<1>元素节点:返回值为null
<2>属性节点:返回值是这个属性的值
<3>文本节点:返回值是这个文本节点的内容
window.onload = function () { //1.元素节点的3个属性 var bjNode = document.getElementById('bj'); alert(bjNode.nodeType);//元素节点:1 alert(bjNode.nodeName);//节点名:li alert(bjNode.nodeValue);//元素节点没有nodeValue属性值:null //2,属性节点 var nameAttr = document.getElementById("name").getAttributeNode("name"); alert(nameAttr.nodeType);//属性节点:2 alert(nameAttr.nodeName);//属性节点的节点名:属性名name alert(nameAttr.nodeValue);//属性节点的nodeValue属性值:属性值 //3.文本节点 var textNode = bjNode.firstChild; alert(textNode.nodeType);//文本节点:3 alert(textNode.nodeName);//文本节点的节点名#text alert(textNode.nodeValue);//文本节点的nodeValue属性值:文本值 }
nodeType、nodeName是只读的
而nodeValue是可以被改变的
以上三个属性,只有在文本节点中使用nodeValue读写文本值时使用最多。
实验一:提示框为文本节点内容
<script type="text/javascript"> window.onload = function () { var cityLi = document.getElementsByTagName("li"); for (var i =0;i<cityLi.length;i++){ cityLi[i].onclick = function () { alert(this.firstChild.nodeValue); } } } </script>
实验二:li节点的文本值没有^^开头,加上,有,则去除。
<script type="text/javascript"> window.onload = function () { var reg = /^^{2}/g; var cityLi = document.getElementsByTagName("li"); for (var i =0;i<cityLi.length;i++){ cityLi[i].onclick = function () { var val = this.firstChild.nodeValue; if (reg.test(val)) { val = val.replace(reg,""); }else { val = "^^"+val; } this.firstChild.nodeValue = val; } } } </script>
8.创建一个元素节点:
1)createElement():按照给定的标签名创建一个新的元素节点。方法只有一个参数:被创建的方法的返回值,是一个指向新建节点的引用指针。返回值是一个元素节点,所以它的nodeType属性值等于1.
新元素节点不会自动添加到文档里,他只是一个存在于javascript上下文的对象。
9.创建一个文本节点:
1)createTextNode():创建一个包含着给定文本的新文本节点。
这个方法的返回值是一个指向新创建文本节点引用指针,
它是一个文本节点,所以它的nodeType属性等于3.
方法只有一个参数,新建文本节点包含的文本字符串,新元素节点不会自动添加到文档里
window.onload = function () { var liNode = document.createElement("li"); var xmText = document.createTextNode("厦门"); liNode.appendChild(xmText); var cityNode = document.getElementById("city"); cityNode.appendChild(liNode); }
练习:选择type添加到该type中li节点
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript"> /**需求1:点击submit按钮时,检查是否选择type,若没有选择给出提示:“请选择类型” * 检查文本框是否输入(可以去除前后空格),若没有输入,则给出提示:“请输入内容” *若检查都通过,则在相应的ul节点中添加对应的li节点 * 需求2:使包括新增的li都能相应onclick事件:弹出li文本值 * */ window.onload = function () { function showContent(liNode) { alert("^_^" + liNode.firstChild.nodeValue); } var liNodes = document.getElementsByTagName("li"); for (let i = 0; i < liNodes.length ; i++) { liNodes[i].onclick = function () { showContent(this); } } //1.获取#submit对应的按钮submitBtn var submit = document.getElementById("submit"); //2.为submitBtn添加onclick响应函数 submit.onclick = function () { //3.在onclick响应函数的结尾添加return false,就可以取消提交按钮的默认行为。 //4.检查是否选择type,若没有选择给出提示:"请选择类型" //4.1选择所有的name="type" 的节点types var types = document.getElementsByName("type"); //4.2遍历types,检查其是否有一个type的checked属性存在,就可以说明 //有一个type被选中了:通过if(元素节点.属性名来判断某一个元素节点是否有该属性。 var typeVal = null; for (var i=0;i<types.length;i++){ if(types[i].checked){ typeVal = types[i].value; break; } } //4.3若没有任何一个type被选中,则弹出:"请选择类型".响应方法结束: //return false if (typeVal == null){ alert("请选择类型"); return false; } //5.获取name="name"的文本值:通过value属性:nameVal var nameEle = document.getElementsByName("name")[0]; var nameVal = nameEle.value; //6.把nameVal和""进行比较,若是""说明只出入了空格,弹出"请输入" var reg = /^s*|s*$/g; nameVal = nameVal.replace(reg,""); //使name的文本框也去除前后空格 nameEle.value = nameVal; if (nameVal == ""){ alert("请输入内容"); return false; } //7.创建li节点 var liNode = document.createElement("li"); //8.利用nameVal创建文本节点 var content = document.createTextNode(nameVal); //9.把8加为7的子节点 liNode.appendChild(content); liNode.onclick = function(){ showContent(liNode); } //10.把7加为选择type对应的ul的子节点 document.getElementById(typeVal).appendChild(liNode); return false; } } </script> </head> <body> <p>你喜欢哪个城市?</p> <ul id="city"> <li id="bj" > 北京</li> <li>上海</li> <li>东京</li> <li>首尔</li> </ul> <br><br> <p>你最喜欢哪个游戏?</p> <ul id="game"> <li id="rl">红警</li> <li>实况</li> <li>极品飞车</li> <li>魔兽</li> </ul> <br><br> <form action="" name="myform"> <input type="radio" name="type" value="city">城市 <input type="radio" name="type" value="game">游戏 name:<input type="text" name="name"> <input type="submit" value="Submit" id="submit"> </form> </body> </html>
11.节点的替换:
1)replaceChild():把一个给定父元素里的一个子节点替换为另外一个子节点
var reference = element.replaceChild(newChild,oldChild);
返回值是一个指向已被替换的哪个子节点的引用指针
2)该节点除了替换功能以外还有移动的功能
3)该方法只能完成单向替换,若需要使用双向替换,需要自定义函数:
//自定义互换两个节点的函数 function replaceEach(aNode,bNode) { //1.获取aNode和bNode的父节点,使用parentNode属性 var aParent = aNode.parentNode; var bParent = bNode.parentNode; if (aParent && bParent){ //2.克隆aNode或bNode var aNode2 = aNode.cloneNode(true); //3.分别调用aNode的父节点和bNode的父节点的replaceChild //方法实现节点的互换 bParent.replaceChild(aNode2,bNode); aParent.replaceChild(bNode,aNode); } }
练习:
实现两个节点互相交换,并且可以再次交换
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript"> window.onload = function () { //1.获取所有的li节点 var liNodes = document.getElementsByTagName("li"); //2.为每一个li节点添加onclick响应函数 for (var i = 0; i < liNodes.length; i++) { liNodes[i].index = i; liNodes[i].onclick = function () { //3.找到和当前节点对应的那个li节点 var targetIndex = 0; if (this.index<4){ targetIndex = 4 + this.index; } else{ targetIndex = this.index -4; } //交换index属性 var tempIndex = this.index; this.index = liNodes[targetIndex].index; liNodes[targetIndex].index = tempIndex; //4.互换 replaceEach(this,liNodes[targetIndex]); } } //自定义互换两个节点的函数 function replaceEach(aNode,bNode) { //1.获取aNode和bNode的父节点,使用parentNode属性 var aParent = aNode.parentNode; var bParent = bNode.parentNode; if (aParent && bParent){ //2.克隆aNode或bNode var aNode2 = aNode.cloneNode(true); //克隆a节点的同时,把onclick事件也复制 aNode2.onclick = aNode.onclick; //交换index属性 aNode2.index = aNode.index; //3.分别调用aNode的父节点和bNode的父节点的replaceChild //方法实现节点的互换 bParent.replaceChild(aNode2,bNode); aParent.replaceChild(bNode,aNode); } } } </script> </head> <body> <p>你喜欢哪个城市?</p> <ul id="city"> <li id="bj" > 北京</li> <li>上海</li> <li>东京</li> <li>首尔</li> </ul> <br><br> <p>你最喜欢哪个游戏?</p> <ul id="game"> <li id="rl">红警</li> <li>实况</li> <li>极品飞车</li> <li>魔兽</li> </ul> <br><br> <form action="" name="myform"> <input type="radio" name="type" value="city">城市 <input type="radio" name="type" value="game">游戏 name:<input type="text" name="name"> <input type="submit" value="Submit" id="submit"> </form> </body> </html>
value:用于获取html表单元素的值
nodevalue:用于获取文本节点的文本值
13.删除节点:
1)removeChild():从一个给定元素里删除一个子节点
var reference = element.removeChild(node);
返回值是一个指向已被删除的子节点的引用指针,
某个节点被removeChild方法删除时,这个节点所包含的所有子节点将同时删除。
如果想删除某个节点,但不知道它的父节点是哪一个,parentNode属性可以帮忙
window.onload = function () { var liNodes = document.getElementsByTagName("li"); for (var i = 0; i < liNodes.length ; i++) { liNodes[i].onclick = function () { var flag = confirm("确认要删除" + this.firstChild.nodeValue + "的信息吗?") if (flag){ this.parentNode.removeChild(this); } } } }
练习:
插入删除员工
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript"> /** * 1.弹出确认对话框:确定要删除xx的信息吗?xx为当前a节点所在td所在的tr的第一个td子节点的文本值,且要去除前后空格。 * 2.若点击“确认”,则删除a节点所在的行 * * 注意: * 1.a节点是一个超级链接,可以在其onclick事件中通过返回false,来取笑默认行为 * 2.tr的直接父节点在tbody,而不是table * 3.可以把去除前后空格的代码写成一个trim(str)函数 * * 为addEmpButton添加onclick响应函数: * 1.获取#name,#email,#salary的文本框的值 * 2.利用1获取文本值创建3个th节点,在创建一个tr节点,并把以上3个th节点加为tr节点的子节点中 * 3.在创建一个th节点:<th><a href="">delete</a></th> * 4.把3创建的td也加为tr的子节点 * 5.再把tr加为employeetable的tbody的子节点的子节点 * 6.为新创建的tr的a子节点添加onclick函数,也具备删除功能 */ function removeTr(aNode) { var trNode = aNode.parentNode.parentNode; var textContent = trNode.getElementsByTagName("th")[0].firstChild.nodeValue; textContent = trim(textContent); var flag = confirm("确定要删除" + textContent + "信息吗?"); if (flag) { trNode.parentNode.removeChild(trNode); } function trim(str) { var reg = /^s*|s*$/g; return str.replace(reg,""); } } window.onload = function () { var aNodes = document.getElementById("employeetable").getElementsByTagName("a"); for (var i = 0; i<aNodes.length;i++){ aNodes[i].onclick = function(){ removeTr(this); return false; } } document.getElementById("addEmpButton").onclick = function () { var nameVal = document.getElementById("name").value; var emailVal = document.getElementById("email").value; var salaryVal = document.getElementById("salary").value; var nameTh = document.createElement("th"); nameTh.appendChild(document.createTextNode(nameVal)); var emailTh = document.createElement("th"); emailTh.appendChild(document.createTextNode(emailVal)); var salaryTh = document.createElement("th"); salaryTh.appendChild(document.createTextNode(salaryVal)); var newTr = document.createElement("tr"); newTr.appendChild(nameTh); newTr.appendChild(emailTh); newTr.appendChild(salaryTh); //delete var aNode = document.createElement("a"); aNode.href=""; aNode.appendChild(document.createTextNode("delete")); var aTd = document.createElement("th"); aTd.appendChild(aNode); newTr.appendChild(aTd); aNode.onclick = function(){ removeTr(this); return false; } document.getElementById("employeetable").getElementsByTagName("tbody")[0].appendChild(newTr); } } </script> </head> <body> <center> <br><br>添加新员工<br><br> name:<input type="text" name="name" id="name" > email:<input type="text" name="email" id="email" > <input type="text" name="salary" id="salary"> <br><br> <button id="addEmpButton">Submit</button> <br><br> <hr> <br><br> <table id="employeetable" border="1" cellpadding="5" cellspacing=0> <tbody> <tr> <th>Name</th> <th>Email</th> <th>Salary</th> <th> </th> </tr> <tr> <th>Tom</th> <th>tom@tom.com</th> <th>5000</th> <th><a href="">delete</a> </th> </tr> <tr> <th>Jerry</th> <th>jerry@tsohu.com</th> <th>8000</th> <th><a href="">delete</a> </th> </tr> </tbody> </table> </center> </body> </html>
12.插入节点:
1)insertBefore():把一个给定节点插入到一个给定元素节点的给定子节点的前面
var reference = element.insertBefore(newNode,targetNode);
节点newNode将被插入到元素节点element中并出现在节点targetNode的前面,节点targerNode必须是element元素额一个子节点。
2)自定义insertAfter()方法
<script type="text/javascript"> window.onload = function () { var cityNode = document.getElementById("city"); var bj = document.getElementById("bj"); var rl = document.getElementById("rl"); /* cityNode.insertBefore(rl,bj);*/ var refNode = document.getElementById("dj"); insertAfter(rl,refNode); } //把newNode插入到refNode的后面 function insertAfter(newNode,refNode) { //1.测试refNode是否为其父节点的最后一个子节点 var parentNode = refNode.parentNode; if (parentNode){ //该父元素节点的最后一个字节点 var lastNode = parentNode.lastChild; //2.若是:直接把newNode插入为refNode父节点的最后一个子节点 if (refNode == lastNode){ parentNode.appendChild(newNode); } //3.若不是:获取refNode的下一个兄弟节点,然后插入到其下一个兄弟节点的前面 else { var nextNode = refNode.nextSibling; parentNode.insertBefore(newNode,nextNode); } } } </script>
14.innerHTML属性
1)浏览器几乎都支持该属性,但不是DOM标准的组成部分
innerHTML属性可以用来读,写某给定元素里的HTML内容
练习:
全选/全不选/反选
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script type="text/javascript"> window.onload = function () { document.getElementById("checkedAll_2").onclick = function () { var flag = this.checked; var items = document.getElementsByName("items"); for (var i = 0;i<items.length;i++){ items[i].checked = flag; } } var items = document.getElementsByName("items"); for (var i = 0; i < items.length; i++) { items[i].onclick = function () { //记录有多少个items被选中了 var number = 0; for (var j = 0; j < items.length; j++) { if (items[j].checked){ number++; } } document.getElementById("checkedAll_2").checked = (items.length==number); } } var checkAll = document.getElementById("CheckedAll"); checkAll.onclick = function () { for (var i = 0 ; i < items.length;i++){ items[i].checked = "checked"; } } var checkno = document.getElementById("CheckedNo"); checkno.onclick = function () { for (var i = 0 ; i < items.length;i++){ items[i].checked = ""; } } var checkrev = document.getElementById("CheckedRev"); checkrev.onclick = function () { for (var i = 0 ; i < items.length;i++){ items[i].checked = !items[i].checked; } } document.getElementById("send").onclick = function () { for (var i = 0; i < items.length; i++) { if (items[i].checked){ alert(items[i].value); } } } } </script> </head> <body> <form method="post" action=""> 你爱好的运动是? <input type="checkbox" id="checkedAll_2">全选/全不选 <br> <input type="checkbox" name="items" value="足球">足球 <input type="checkbox" name="items" value="篮球" >篮球 <input type="checkbox" name="items" value="羽毛球">羽毛球 <input type="checkbox" name="items" value="乒乓球">乒乓球 <br> <input type="button" id="CheckedAll" value="全选"> <input type="button" id="CheckedNo" value="全不选"> <input type="button" id="CheckedRev" value="反选"> <input type="button" id="send" value="提交"> </form> </body> </html>