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 οnclick="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>