zoukankan      html  css  js  c++  java
  • JavaScript(三)-- DOM编程

    JavaScript编程中最基本的就是DOM编程,DOM是 Document Object Model文本对象模型,就是对DOM对象进行编程的过程。

    Java语言和Js都有针对于DOM的编程,两者类似,主要是有一套DOM编程的规范,两者都遵循这样的规范。

    这里主要讲Js的DOM编程API

    DOM是针对xml(html)基于树的API

    DOM树就是节点Node的层次

    DOM将文档作为一颗树进行处理,定义了Node节点接口,用节点表示xml中各种信息;

    节点分为三种类型:元素节点、属性节点、文本节点

    当中。属性节点和文本节点都是元素节点的子节点,元素节点的子节点能够是属性节点、文本节点,也能够是元素节点

    属性节点是元素节点的属性。能够直接通过属性的方式操作

    文本节点是元素节点的子节点。通常为文本的形式。

    一个简单的样例:

    能够看出js中的对象以及方法的调用

    window和document都是js的对象,onload和onclick都是对象的事件,能够通过为事件赋值函数的方法,在函数中指定事件发生时,要运行的操作

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    <script type="text/javascript">
    	//1.window是js中的一个对象,onload是该对象的一个事件,为其赋值一个函数
    	//即:在window对象的onload事件触发时,载入后边的函数
    	window.onload = function(){
    		//2.利用对象document的方法getElementsByTagName("")从DOM中获取节点对象。并取得第一个对象
    		var btn = document.getElementsByTagName("button")[0];
    		//3.为对象btn的onclick事件赋值函数。当事件触发时。载入后边的函数
    		btn.onclick = function(){
    			//4.弹出"helloworld"
    			alert("helloworld");
    		}
    	}
    </script>
    </head>
    <body>
    	<button>Click me!</button>
    </body>
    </html>

    1、js代码写在什么位置

    js代码的位置一般写在html文档中的head节点下的title子节点后边。


    js代码也能够和html代码耦合着写。这样针对于比較少的js代码,可是一般不建议这样写:

    <body>
    	<!-- html和js代码耦合在一起 ,代码少的话,能够这样,可是一般不这样写-->
    	<button onclick="alert('helloworld')">Click me!</button>
    </body>
    为节点button的onclick属性事件直接赋值函数。

    必需要html文档全然载入之后。才干获取节点,所以能够把js代码放在html文档之后。

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    
    </head>
    <body>
    	<button >Click me!</button>
    </body>
    </html>
    <!-- 在整个html文档载入之后,获取当中的节点,js代码放在html文档之后 -->
    <script type="text/javascript">
    	var btns = document.getElementsByTagName("button");
    	alert(btns.length);//输出结果为1
    </script>
    缺点是:不符合写js代码的习惯

    通常将js放在titile的后边,等待文档载入后才运行js代码的操作是为window.onload事件赋值函数操作。

    window.onload事件在文档被全然载入后触发。

    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    <script type="text/javascript">
    	window.onload = function(){
    		//全部的js代码写在window.onload赋值的函数中
    		var btns = document.getElementsByTagName("button");
    		alert(btns.length);//输出结果为1
    	}
    </script>
    </head>

    2、获取节点

    获取元素节点

    获取元素节点有三种方法:依据id获取、依据标签名获取元素集合、依据name属性获取元素集合

    基本都是依据document对象的方法获取。当中getElementsByTagName依据标签名获取,这种方法是Node接口的方法。不论什么节点对象都有这种方法。

    能够用这种方法获取指定节点的子节点

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    <script type="text/javascript">
    	window.onload = function(){
    		//1.依据节点的id获取节点对象。注意在编写html文档时,id 要唯一
    		//getElementById为document对象的方法
    		var bjNode = document.getElementById("bj");
    		alert(bjNode);
    		
    		//2.使用标签名获取指定节点的集合
    		//getElementsByTagName方法事Node接口的方法,即不论什么节点对象都有该方法
    		var lis = document.getElementsByTagName("li");
    		alert(lis.length);//值为8
    		
    		//即不论什么节点对象都有该方法getElementsByTagName
    		//获取指定节点city的li子节点的个数
    		var cityNode = document.getElementById("city");
    		var cityLis = cityNode.getElementsByTagName("li");
    		alert(cityLis.length);//输出值为4
    		
    		//3.依据元素的name属性来获取指定节点的集合,由于名字可反复。故结果为集合
    		var genderNode = document.getElementsByName("gender");
    		alert(genderNode.length);//输出值为2
    		
    		//若HTML元素自身未定义name属性。则该方法对于IE 无效,使用该方法时需慎重
    		//li元素本身没有name属性
    		var bjNode2 = document.getElementsByName("BeiJing");
    		alert(bjNode2.length);
    	}
    </script>
    </head>
    <body>
    	<p>你喜欢哪个城市?</p>
    	<ul id="city">
    		<li id="bj" name="BeiJing">北京</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>
    	
    	gender
    		<input type="radio" name="gender" value="male"/>Male
    		<input type="radio" name="gender" value="female"/>Female
    </body>
    </html>

    获取属性节点

    读写属性节点,就是读写元素节点的属性。通过元素节点"."的方式获取和读写属性

    先获取元素节点,再通过元素节点.得到属性值

    <script type="text/javascript">
    	//读写属性节点,属性节点即为某一指定节点元素的属性:通过元素节点.的方式获取属性值和设置属性值
    	window.onload = function(){
    		//1.先获取指定的元素节点
    		var nameNode = document.getElementById("name");
    		//2.再读取指定属性的值
    		alert(nameNode.value);
    		//3.设置指定属性的值
    		nameNode.value="yuchen";
    		
    	}
    </script>
    </head>
    <body>
    
    	name:
    		<input type="text" name="username" id="name" value="cqupt"/>
    </body>

    获取元素节点的子节点

    获取元素节点的子节点,也是先获取到元素节点,

    通过元素节点的childNodes获取元素节点的全部子节点,

    通过getElementsByTagName()获取指定标签子节点,

    通过firstChild和lastChild获取第一个子节点和最后一个子节点。

    <script type="text/javascript">
    	window.onload = function(){
    		//1.获取#city节点的全部子节点
    		var cityNode = document.getElementById("city");
    		//2.利用元素节点的childNodes方法获取指定节点元素的全部子节点,但该方法不有用
    		alert(cityNode.childNodes.length);//输出为9,对于ul中。有文本节点和li元素节点
    		//3.获取#city节点的全部li子节点
    		var lis = cityNode.getElementsByTagName("li");
    		alert(lis.length);
    		//4.获取指定节点的第一个子节点和最后一个子节点
    		alert(cityNode.firstChild);
    		alert(cityNode.lastChild);
    	}
    </script>

    获取文本节点

    文本节点一定是元素节点的子节点。先通过获取元素节点,再定位到文本节点,通过文本节点的nodeValue属性读写文本值。

    <script type="text/javascript">
    	//文本节点一定是元素节点的子节点
    	window.onload = function(){
    		//1.获取元素节点
    		var bjNode = document.getElementById("bj");
    		//2.通过firstChild定位到文本节点
    		var bjTextNode = bjNode.firstChild;
    		//3.通过文本节点的nodeValue属性读取文本值
    		alert(bjTextNode.nodeValue);
    		//4.通过文本节点的nodeValue属性改变文本值
    		bjTextNode.nodeValue = "重庆";//“重庆”替换掉“北京”
    	}
    </script>

    3、两个练习

    for循环和函数中的this

    练习1:点击全部li标签元素时,弹出该元素节点的文本值

    for循环,变量都是var定义的for(var i=0;i<nodes.length;i++){}

    在函数中,this代表触发的元素节点,不能够使用i来定位节点

    <script type="text/javascript">
    window.onload = function(){
    	//1.获取全部标签li的元素集合
    	var liNodes = document.getElementsByTagName("li");
    	//2.通过for循环,获取元素集合中的每一个元素节点,
    	for(var i=0;i<liNodes.length;i++){
    		//3.为元素节点的onclick事件赋值函数
    		liNodes[i].onclick = function(){
    			//4.函数中this代表当前触发的元素节点。firstChild方法获取元素节点的文本节点
    			var liTextNode = this.firstChild;
    			//5.获取文本节点的值
    			alert(liTextNode.nodeValue);
    			
    			//不能够使用i来定位元素,由于事件触发是发生在。赋值函数完毕后,
    			//触发事件时,i的值已经变为liNodes.length,而此时liNodes[i]不运行不论什么节点
    			//var liTextNode = liNodes[i].firstChild
    			
    		}
    	}
    }
    </script>

    函数的编写与使用

    上述事件触发都是直接为事件赋值函数。事实上函数能够单独定义。然后在事件触发处引用。前边使用的都是匿名函数

    <script type="text/javascript">
    	window.onload = function(){
    		var but = document.getElementById("but");
    		//使用函数的引用,假设在引用后加(),也就是hello(),那么文档载入时就会运行函数,把函数运行的结果赋值给事件
    		but.onclick = hello();
    		//单独定义函数。然后在事件触发出使用函数的引用
    		function hello(){
    			alert("helloworld")
    		}
    	}
    </script>
    不使用匿名函数也能够

    <script type="text/javascript">
    	window.onload = function (){
    		var but = document.getElementById("but");
    		//不使用匿名函数也能够。能够为韩式指定名字,一般直接为事件赋值函数时。使用匿名函数
    		but.onclick = function hello(){
    			alert("helloworld")
    		}
    	}
    </script>

    if推断和正則表達式

    正則表達式是对字符串操作非常有效的方法,须要细致研究下。

    练习2:对每一个li元素的文本值,假设是以^^開始。那么在点击时取消^^;假设没有^^。那么点击时,加上^^

    正則表達式的使用样例:

    <script type="text/javascript">
    	window.onload = function (){
    		var str1="^^abc";
    		var str2="abc";
    		var reg = /^^{2}/g;//正則表達式
    		
    		//利用正則表達式判读字符串中是否含有^^
    		alert(reg.test(str1));
    		alert(reg.test(str2));
    		//利用正則表達式。将字符串中的^^替换为""
    		alert(str1.replace(reg,""));
    	}
    </script>
    练习的代码

    <script type="text/javascript">
    window.onload = function(){
    	var liNodes = document.getElementsByTagName("li");
    	
    	for(var i=0;i<liNodes.length;i++){
    		liNodes[i].onclick = function(){
    			var reg = /^^{2}/g;//正則表達式
    			var val = this.firstChild.nodeValue;
    			if(reg.test(val)){
    				val = val.replace(reg,"");
    			}else{
    				val= "^^"+val;
    			}
    			//记得最后要把文本值给替换
    			this.firstChild.nodeValue = val;
    		}
    	}
    }
    </script>

    4、节点的属性

    节点的属性与属性节点不同。三种节点都有属性。

    每种节点都有三个属性:nodeType、nodeName、nodeValue

    不同种类的节点的三种属性不同,而id,name,type是详细节点的属性

    <script type="text/javascript">
    	window.onload = function(){
    		var bjNode = document.getElementById("bj");
    		alert(bjNode.nodeType);//元素节点 ,值为1
    		alert(bjNode.nodeName);//节点标签名:LI
    		alert(bjNode.nodeValue);//元素节点没有nodeValue值,为:null
    		
    		//<input type="text" name="username" id="name" value="cqupt"/>
    		var nameAttr = document.getElementById("name").getAttributeNode("name");
    		alert(nameAttr.nodeType);//属性节点 ,值为2
    		alert(nameAttr.nodeName);//节点属性名:name
    		alert(nameAttr.nodeValue);//属性值:username
    		
    		var bjTextNode = document.getElementById("bj").firstChild;
    		alert(bjTextNode.nodeType);//文本节点 ,值为3
    		alert(bjTextNode.nodeName);//节点名:#text
    		alert(bjTextNode.nodeValue);//值为文本节点本身的值:北京
    		
    		//nodeType 和 nodeName是仅仅读的
    		//nodeValue是能够改变的
    	}
    </script>
    通过元素节点.的方式获取到的属性,不具有节点的特性。没有这三种属性。仅仅有通过getAttributeNode()的方法获取到的属性节点才具有这三种属性

    5、创建并增加节点

    创建元素节点:var liNode = document.createElement("li"),依据标签名创建元素节点

    创建文本节点:var liText = document.createTextNode("str")。依据文本字符串创建文本节点

    将文本节点增加为元素节点的子节点:liNode.appendChild(liText);

    练习:

    需求:在点击submit时,推断是否选择type。若没有选择,给出提示“请选择类型”;
    检查文本框中是否有内容(去除前后空格)。若没有,给出提示“请输入内容”;
    若检查都通过。在对应的ul下加入li节点

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    <script type="text/javascript">
    	window.onload = function(){
    		//1.获取submit相应的节点submitBtn
    		var submitBtn = document.getElementById("submit");
    		//2.为submitBtn加入onlcick响应函数
    		//3.在onclick函数的结尾处加入return false。能够取消提交button的默认行为
    		submitBtn.onclick= function(){
    			//4.检查是否选择type类型,若没有,给出提示
    			//4.1选择全部的name="type"的节点集types
    			var types = document.getElementsByName("type");
    			//4.2遍历types,查看是否有一个type的checked属性存在,就能够说明有一个type元素被选中了:
    			var typeVal=null;
    			for(var i=0;i<types.length;i++){
    				//用if(节点.属性名)来推断某一个节点是否有该属性
    				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 nameVal=document.getElementsByName("name")[0].value;
    			//6.去除nameVal的前后空格
    			var reg=/^s*|^s*/g;
    			nameVal = nameVal.replace(reg,"");
    			//6.将nameValde 值与""做进行比較,若相等,提示。函数响应结束。返回return false
    			if(nameVal==""){
    				alert("请输入内容");
    				return false;
    			}
    			//7.创建li节点
    			var liNode = document.createElement("li");
    			//8.创建文本节点liText,利用nameVal
    			var liText = document.createTextNode(nameVal);
    			//9.把liText节点加为li的子节点
    			liNode.appendChild(liText);
    			//10.把li加为ul的子节点
    			var ulNode = document.getElementById(typeVal);
    			ulNode.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>
    	
    	<form action="js-1.html" 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>
    注意 :

    1.变量为null的使用

    2.怎样推断元素属性存在与否if(元素.属性名)

    3.属性注明时,规范做法是checked="checked"

    6、替换节点

    替换节点。使用 父节点.replaceChild(newNode, oldNode)方法,把一个给定父元素里的指定节点替换为还有一个节点。

    返回值是一个运行被替换掉的节点的引用指针。即指向oldNode的指针

    替换节点。还有移动的效果。被替换的节点从页面显示上消失,替换的节点从原来的位置转移到被替换的位置。

    该方法仅仅能单向替换。若实现双向替换,那么须要自定义函数

    <script type="text/javascript">
    	window.onload = function(){
    		//替换节点:父类节点.replaceChild(newNode, oldNode)
    		//克隆节点:节点.cloneNode(true)深度克隆为true(将子节点一起克隆)
    		//节点替换具有移动的效果。被替换的节点显示消失(但节点还存在)。替换节点从原位置转移到替换节点处
    		var bjNode = document.getElementById("bj");
    		var rlNode = document.getElementById("rl");
    		replaceEach(bjNode,rlNode);
    	}
    	//函数定义可写在其它函数的外部,也能够写在内部
    	//注意:定义函数时。參数不能写var类型。直接參数名
    	function replaceEach(aNode,bNode){
    		var aParent = aNode.parentNode;
    		var bParent = bNode.parentNode;
    		//克隆当中一个节点。用克隆节点去替换还有一节点
    		var clone = aNode.cloneNode(true);
    		//替换过程
    		if(aParent && bParent){
    			//replaceChild函数的返回值是一个指向被替换的节点的引用指针
    			var node = bParent.replaceChild(clone,bNode);
    			alert(node.firstChild.nodeValue);//红警
    			aParent.replaceChild(bNode,aNode);
    		}
    	}
    </script>

    练习:点击city中的li标签,与game中的对应li标签对换

    注意:节点克隆时,事件属性不会克隆(克隆产生的节点不具有事件响应,可是替换节点中事件会保持),需手动复制。

    自己加入的属性也不会克隆,自己加入属性的方法就是直接:节点.index=45 或者节点.aa="23",对名称无要求。

    关键就在事件的复制。与使用index属性的记录下标,交换节点时,也要交换下标

    <script type="text/javascript">
    	window.onload = function(){
    		//1.为全部的li标签加入onclick事件。赋值函数
    		var liNodes = document.getElementsByTagName("li");
    		for(var i=0;i<liNodes.length;i++){
    			//为节点加入index属性,用以记录下标值
    			liNodes[i].index=i;
    			liNodes[i].onclick = function(){
    				
    				var targetIndex = (this.index+4)%8;
    				//alert(targetIndex);
    				//先交换index属性值
    				var tempIndex = this.index;
    				this.index = liNodes[targetIndex].index;
    				liNodes[targetIndex].index = tempIndex;
    				
    				replaceEach(this,liNodes[targetIndex]);
    			}
    		}
    	}
    	function replaceEach(aNode,bNode){
    		var aParent = aNode.parentNode;
    		var bParent = bNode.parentNode;
    		
    		if(aParent && bParent){
    			var clone = aNode.cloneNode(true);
    			//事件onclick须要手动克隆
    			clone.onclick = aNode.onclick;
    		
    			bParent.replaceChild(clone,bNode);
    			aParent.replaceChild(bNode,aNode);
    		}
    	}
    </script>

    7、删除节点

    删除节点的方法:父节点.removeChild(node),通常在事件响应函数中。使用this.parentNode.removeChild(this)

    练习:对每一个li元素节点加入响应函数,通过确认对话框,删除该节点

    确认对话框的使用:confirm("确定要删除。。

    信息吗?")。返回值为布尔值

    <script type="text/javascript">
    	window.onload = function(){
    		//删除节点:父节点.removeChild(node)
    		var liNodes = document.getElementsByTagName("li");
    		for(var i=0;i<liNodes.length;i++){
    			liNodes[i].onclick = function(){
    				//confirm(""):确认对话框,返回值为布尔值
    				var flag = confirm("确定要删除:"+this.firstChild.nodeValue+" 信息吗?");
    				if(flag){
    					this.parentNode.removeChild(this);
    				}
    			}
    		}
    	}
    </script>

    8、插入节点

    前边讲了创建并增加节点。使用的是appendChild(newNode)方法,这种方法是将新建的节点加到最后一个子节点之后。

    假设指定插入到某个节点之前。就要使用insertBefore(newNode, existingChild),要指明哪一个子节点

    没有insertAfter方法。可是能够依据使用insertAfter方法变相完毕:

    function insertAfter(newEl, targetEl)
    {
        var parentEl = targetEl.parentNode;
                
         if(parentEl.lastChild == targetEl)
         {
               parentEl.appendChild(newEl);
          }else
          {
               parentEl.insertBefore(newEl,targetEl.nextSibling);
           }            
    }
    nextSibling是属性。返回当前节点的下一节点,假设没有同级的下一节点,返回null

    previousSibling是返回节点的上一同级节点

    9、innerHTML属性

    innerHTML属性返回表格中行的開始和结束标签之间的HTML代码比如:

    <table border="1">
    <tr id="tr1">
    <th>Firstname</th>
    <th>Lastname</th>
    </tr>
    <tr id="tr2">
    <td>Peter</td>
    <td>Griffin</td>
    </tr>
    </table>
    那么
     alert(document.getElementById("tr1").innerHTML);
    显示的是
    <th>Firstname</th>

    <th>Lastname</th>



  • 相关阅读:
    如何查找本地的ip
    jQuery解析AJAX返回的html数据时碰到的问题与解决
    angularjs之ng-bind和ng-model
    nodejs配置及cmd常用操作
    ID属性值为小数
    DOM对象
    js跨域问题
    加载图片失败,怎样替换为默认图片
    常用前端 网址
    echart字符云之添加点击事件
  • 原文地址:https://www.cnblogs.com/mthoutai/p/7282039.html
Copyright © 2011-2022 走看看