重看Javascript高级程序设计,第10章:DOM

本章内容

  1. 理解包含不同层次节点的DOM
  2. 使用不同的节点类型
  3. 克服浏览器兼容性问题及各种陷阱

DOM(文档对象模型)是针对HTML和XML文档的一个API(应用程序编程接口)。DOM描绘了一个层次化的节点树,允许开发人员添加、移除和修改页面的某一部分。

10.1 节点层次

DOM可以将任何HTML或XML文档描绘成一个由多层节点构成的结构。以下面的HTML为例:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<p>Hello World</p>
	</body>
</html>

以上例子中。文档节点只有一个子节点,即<html>元素,我们称之为文档元素。文档元素是文档的最外层元素,其他所有元素都包含在文档元素中。每个文档只能有一个文档元素。在HTML页面中。文档元素始终是<html>元素。而在XML中由于没有预定义的元素,所有任何元素都可以是文档元素。

function conToArray(nodes){
				var array = null;
				try{
					//针对非ie浏览器
					array = Array.prototype.slice.call(nodes,0)
				} catch(ex){
					array = new Array()
					for(var i = 0;i<nodes.length;i++){
						array.push(nodes[i])
					}
				}
				return array
			}
			
			//如果列表中只有一个节点,那么该节点的nextSibling和previousSibling都为null
			if(someNode.nextSibling === null){
				alert('到底了')
			}else if(someNode.perviousSibling === null){
				alert('上面也没了')
			}
			
			//新增节点
			var result = someNode.appendChild(newNode)
			alert(result == newNode)						//true
			alert(someNode.lastChild == newNode)			//true
			
			//someNode有多个子节点
			var re = someNode.appendChild(someNode.firstChild)
			alert(re == someNode.firstChild)				//false
			alert(re == someNode.lastChild)					//true
			
			//插入节点
			//使用insertBefore().接收两个参数:要插入的节点和作为参照的节点.如果参照节点是null.则insertBefore和appendChild执行相同操作.如下:
			//插入后成为最后一个子节点
			re = someNode.insertBefore(newNode,null)
			alert(newNode == someNode.lastChild)			//true
			
			//插入后成为第一个子节点
			var r = someNode.insertBefore(newNode,someNode,firstChild)
			alert(r == newNode) 							//true
			
			//插入最后一个子节点前面
			r = someNode.insertBefore(newNode,someNode.lastChild)
			//注意.appendChild和insertBefore方法都只是插入节点,不会移除节点.
			//replaceChild方法接收两个参数:要插入的节点和要替换的节点.要替换的节点将由这个方法返回的文档树中移除.同时由要插入的节点占据位置.如下:
			//替换第一个子节点
			var n = someNode.replaceChild(newNode,someNode.firstChild)
			//替换最后一个子节点
			n = someNode.replaceChild(newNode,someNode.lastChild)
			
			//移除节点 removeChild()接收一个参数.即要移除的节点.被移除的节点将成为方法的返回值,如下:
			//移除第一个子节点
			n = someNode.removeChild(someNode.firstChild)
			//移除最后一个子节点
			n = someNode.removeChild(someNode.lastChild)
			
			//上面介绍的4个方法操作都是某个节点的子节点.也就是说使用这几个方法必须先取得父节点.使用parentNode属性.并不是所有类型的节点都有子节点.
			
			//深复制
			var deepList = myList.cloneNode(true)
			alert(deepList.childNodes.length)				//3		ie<9或7
			
			//浅复制
			var slit = myList.cloneNode(false)
			alert(slit.childNodes.length)					//0
			
			
			//normalize()方法作用是处理文档树中的文本节点.由于解析器实现或DOM操作的原因.会出现文本节点不包含文本,或者链接出现两个文本节点的情况.在某个节点调用这个方法,就会找到上述两种情况.找到空文本节点,则删除它.找到相邻的文本节点就合并成一个.

1.2 Document 类型

//访问子节点
			var html = document.documentElement;
			console.log(html === document.childNodes[0])				//true
			console.log(html === document.firstChild[0])				//true
			//document对象还有个body属性,直接指向<body>元素.
			var body = document.body
			//取得对<!DOCTYPE>的引用
			var doctype = document.doctype

2. 文档信息

//取得文档的标题
			var title = document.title
			//设置文档标题
			document.title = '我是文档标题'
			
			//取得完整的URL;
			var url = document.URL;
			//取得域名
			var domain = document.domain;
			//取得来源页面的URL;
			var referrer = document.referrer;
			
			//出于安全考虑,domain并非可以设置任何值.不能将这个属性设置为URL中不包含的域.如下:
			//假设页面来自p2p.wrox.com域
			document.domain = 'wrox.com'				//成功
			document.domain = 'www.baidu.com'			//失败
			//域名一开始是a,如果用domain设置成b,那它将不能在设置回a.

3. 查找元素

 getElementById()和getElementsByTagName()

//getElementById()查找元素 
			//根据ID查找元素.ID必须与HTML里面的ID完全一致.区分大小写
			var div = document.getElementById('divName')
			//根据标签名查找元素
			//getElementsByTagName()返回的是一个或多个元素的nodeList
			var img = document.getElementsByTagName('img')
			//保存的img集合可以通过下列方式访问
			console.log(img.length)
			console.log(img[0].src)
			console.log(img.item(0).src)
			//如果img集合中包含有个name属性的.可以通过下面方式访问
			var imgName = img.namedItem('imgName')
			//也可以通过方括号语法来访问.如下:
			var imgName = img['imgName']
			//在后台,对数值索引就调用item(),对字符串索引就调用namedItem()
			//getElementsByTagName('*')表示全部
			var all = document.getElementsByTagName('*')
			
			//第三个方法.getElementsByName().返回带有给定name特性的所有元素.常用于单选
			var radios = document.getElementsByName('color')
			
			//包含文档中所有带name属性的a元素
			var a = document.anchors;
			//包含文档中所有form元素,与document.getElementsByTagName('form')结果相同
			var form = document.forms;
			//包含文档中所有img元素
			var img = document.images
			//包含文档中所有带href属性的元素
			var link = document.links

6. 文档写入

 write()、writeIn()、open()、close()。

write和writeIn方法接收一个字符串参数,即要写入的文本。write会原样写入。writeIn会在末尾加一个\n换行符。


			//文档写入字符串
			document.write('<b>我是写入文档</b>')
			//也可以写入js文件;
			document.writeIn('<script type="text/javascript" src="file.js"></script>')
			
			//open和close的作用是打开和关闭页面

1.3 Element类型

Element类型用于表现XML或HTML元素。 

//取得标签名
			var div = document.getElementById('mydiv')
			console.log(div.tagName)
			//nodeName也可以取得标签名
			console.log(div.tagName === div.nodeName)
			//在HTML中,标签名始终都以大写表示,通过如下方式转换
			console.log(div.tagName.toLowerCase())					//结果为div;

1.HTML元素

所有HTML元素都由HTMLElement的子类型来表示 。HTMLElement类型直接继承Element并添加了一些属性。

  • id,元素在文档中的唯一标识
  • title,有关元素的附加说明信息,一般通过工具提示条显示出来
  • lang,元素内容的语言代码,很少用
  • dir,语言的方向,值为“ltr”或“rtl”
  • className,与元素的class特性对应,即为元素指定的css类。没有将这个属性命名为class,是因为class是ES中的保留字。

 以下是上述属性的使用方法:

//取得id;
			var id = document.getElementById('mydiv');
			//标题
			console.log(id.title)
			//class
			console.log(id.className)
			//lang
			console.log(id.lang)
			//dir
			console.log(id.dir)
			//也可以通过下面方式赋值
			//标题
			id.title = 'new text';
			//class
			id.className = 'newClass'
			//lang
			id.lang = 'fr'
			//dir 
			id.dir = 'rtl'

2.取得特性(属性)

 操作特性的方法为:getAttribute()、setAttribute()、removeAttribut()。如下使用方式:

//操作特性(属性)
			//获取id属性
			console.log(id.getAttribute('id'))
			//获取class属性	传入的字符串必须用特性名称保持一致.如果没找到传入的特性名称,则显示null
			console.log(id.getAttribute('class'))
			//也可以获取自定义特性
			console.log(id.getAttribute('zidingyi'))
			//获取style;
			console.log(id.getAttribute('style'))
			//onclick;
			console.log(id.getAttribute('onclick'))

3.设置特性

//设置特性
			id.setAttribute('id','newId')
			id.setAttribute('class','newClass')
			//也可以如下:
			id.id = 'newIdd';
			id.className = 'newclassss'
			
			//removeAttribute()不仅会清除特性的值,还会从元素中完全删除特性
			id.removeAttribute('class')

//遍历元素特性函数
			function bl(element){
				var pains = new Array(),
					attrName,
					attrValue,
					for(let i = 0;i<element.length;i++){
						attrName = element.attributes[i].nodeName
						attrValue = element.attributes[i].nodeValue
						pains.push(attrName + '=' + attrValue)
					}
					return pains.join(" ")
			}

 5.创建元素

//创建元素
			var d = document.createElement('div')
			//新创建的元素可以直接添加属性
			d.id = 'newid'
			d.className = 'newClass'
			d.innerText = '1111'
			//将新创建的元素添加到DOM里
			document.body.appendChild(d) 

 6. 元素子节点

//获取子节点
			var ul = document.getElementById('ul')
			var li = ul.getElementsByTagName('li')
			console.log(li)

1.4 Text类型

 下列方法可以操作节点中的文本:

appendData(text):将text添加到节点的末尾。

deleteData(offset,count):从offset指定的位置开始删除count个字符。

insertData(offset,text):从offset指定的位置插入text。

replaceData(offset,count,text):用text替换指定的位置从offset开始到count结束。

splitText(offset):从offset指定的位置将文本节点分为两个文本节点。

substringData(offset,count):提取从offset指定的位置开始到offset+count为止处的字符串。

除此之外,文本节点还有一个length属性。保存着节点中字符的数目。

可以用以下代码来访问文本子节点:

//访问文本子节点
			var textNode = div.firstChild;				//或者div.childNodes[0]
			//取得之后可以用下列方式修改它
			div.firstChild.nodeValue = "修改过后的值"

1. 创建文本节点

//创建文本节点
			var t = document.createTextNode('<b>Hello</b> wolrd')
			var er = document.createElement('div')
			er.className = 'message'
			var er1 = document.createTextNode('我是message div里面的值')
			er.appendChild(er1)
			var er2 = document.createTextNode('我是message div里面后创建的值')
			er.appendChild(er2)
			document.body.appendChild(er)

2.  规范化文本节点

//规范化文本节点
			console.log(er.childNodes.length)
			er.normalize()
			console.log(er.childNodes.length)
			console.log(er.firstChild.nodeValue)

3. 分割文本节点

//分割文本节点
			var fg = er.firstChild.splitText(5)
			console.log(er.firstChild.nodeValue)
			console.log(fg.nodeValue)
			console.log(er.childNodes.length)

文档片段用法

//文档片段
			var fra = document.createDocumentFragment()
			var ul = document.getElementById('myul')
			var li = null;
			for(var i = 0;i<5;i++){
				li = document.createElement('li')
				li.appendChild(document.createTextNode('我是第' + i + '个li'))
				// li.innerText = '我是第' + i + '个li'
				fra.appendChild(li)
			}
			ul.appendChild(fra)

 1.9 attr 类型

//操作元素的特性
			var attr = document.createAttribute('align')
			attr.value = 'left'
			div.setAttributeNode(attr)
			console.log(div.attribute('align').value)
			console.log(div.getAttributeNode('align').value)
			console.log(getAttribute('align'))

 2. 动态脚本

2.1 插入动态脚本

//插入动态脚本函数
			function loadJs(url){
				var script = document.createElement('script')
				script.type = 'text/javascript'
				script.src = url
				document.body.appendChild(script)
			}
			loadJs('jquery.min.js')
			
			//也可以用这种方式
			var script1 = document.createElement('script')
			script1.type = 'text/javascript'
			var code = 'function sayHi(){alert("hi")}'
			try{
				script1.appendChild(document.createTextNode('code'))
			} catch(ex){
				script1.text = 'code'
			}
			document.body.appendChild(script1)

2.2 动态样式

//动态样式
			function loadCss(url){
				var link = document.createElement('link')
				link.rel = 'stylesheet'
				link.type = 'text/css'
				link.href = url
				var head = document.getElementsByTagName('head')[0]
				head.appendChild(link)
			}

 2.3 操作表格

//创建表格
			var table = document.createElement('table')
			table.border = 1
			table.width = '100%'
			var tbody = document.createElement('tbody')
			table.appendChild(tbody)
			//创建第一行
			tbody.insertRow(0)
			tbody.rows[0].insertCell(0)
			tbody.rows[0].cells[0].appendChild(document.createTextNode('cell 1,1'))
			tbody.rows[0].insertCell(1)
			tbody.rows[0].cells[1].appendChild(document.createTextNode('cell 2,1'))
			//创建第二行
			tbody.insertRow(1)
			tbody.rows[1].insertCell(0)
			tbody.rows[1].cells[0].appendChild(document.createTextNode('cell 1,2'))
			tbody.rows[1].insertCell(1)
			tbody.rows[1].cells[1].appendChild(document.createTextNode('cell 2,2'))
			//插入到页面里
			document.body.appendChild(table)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值