1. DOM的全称 Document Object Model
2. DOM定义了表示和修改文档所需的方法。
3. DOM对象即为宿主对象,由浏览器厂商定义,用来操作html和xml功能的一类对象的集合,也有人称DOM是对HTML和XML的标准编程接口。
DOM修改不了CSS样式表,只能通过间接的方式修改HTML中的行间样式。
节点的类型
每个节点都会有对应的数值,
元素节点 ----- 1 (例如htnl里的标签,script,body,div,p...)
属性节点 ----- 2 (...)
文本节点 ----- 3 (标签中的间隔就是文本节点类型的...)
注释节点 ----- 8 (文档中的注释)
document ----- 9
DocumentFragment ----- 11
节点的四个属性
一段仅供测试使用的代码
测试
文字
1. nodeName
判断元素的节点类型,元素的标签名以大写的形式表示(只读)
2. nodeValue
Text 节点或 Comment(注释) 节点才有的属性,可读写文本内容。
3. nodeType
判断节点的类型
每个节点类型都对应一个值,可以使用nodeType查看。
4. attributes
Element节点的属性结合。
把元素节点当作属性放到一个类数组里。
5. Node.hasChildNodes()
这是一个方法,用来判断元素有没有子节点。有的话返回true,反之返回false
1. 使用方法选择元素
¤ document代表整个文档
html标签也在document之内
¤ document.getElementById('') // 选择对应的id元素。
扩展:元素ID在IE8以下的浏览器,不区分大小写。而且name属性的元素可以当成id元素使用。
¤ document.getElementsByTagName('') // 选择对应的标签元素。
选择后会是一个类数组
¤ document.getElementsByName('') //选择对应的name属性元素,
常用的标签(有表单,表单元素,img,iframe)
¤ document.getElementsByClassName('')
·//根据类名选择元素,ie8及以下版本不支持。
##凡是选出来的是一组元素的,都需要以数组的方式来调用,例如:
document.getElementsByTagName('')[0];
¤ document.querySelector() 选出来的是一个元素
¤ document.querySelectorAll() 选出来的是一组元素
这两个方法功能一样的,都是根据选择器来选择元素
参数里正常填写 CSS选择器 ,例如
文字
缺点:
IE7及以下版本不支持。不实时,相当于把现有的选择器做了一个副本,即使后续在添加或者是删除,也不会影响这个备份里的元素。
可以正常操作HTML中标签,不经常使用。
不一定非要使用方法选择元素,也可以使用遍历节点...
2. 遍历节点树
每个DOM元素身上都有这个属性,里面存储的是它的父节点。
文字
控制台测试输出
测试
文字
控制台测试输出body的子节点组
使用以上代码控制台测试:
3. 遍历元素节点树
4.DOM继承树
document 的构造函数是 HTMLDocument ,HTMLDocument构造函数的原型是 HTMLDocument {…}
HTMLDocument {…}(原型) 的 __proto__ 里有Document
Document 里的 __proto__ 里有 Node
一直看下去的话会发现最终原型是 Object{...}
继承树表示的其实是一种继承关系,
1. getElementById 方法定义在 Document.prototype 上,即 Element 节点上不能使用。
说明HTML和XHTML都可以使用 getElementById
2. getElementsByName 方法定义在 HTMLDocument.prototype 上,即非 html 中的 document不能使用(xhtml...)
3. getElementsByTagName 方法定义在 Document.prototype 和 Element.prototype 上document和标签Element元素都可以调用getELementByTagName
4. HTMLDocument.prototype 定义了一些常用的属性,body , head 分别指代HTML文档中的标签document.body 和 document.head 分别指的是body标签和head标签
5. Document.prototype 上定义了 documentElement 属性,指代文档的根元素,在HTML文档中,它总是指代元素document.documentElement 指的是 html 标签
6. getElementsByName , querySeleCtorAll , querySelector 在 Document.prototype, Element.prototype 类中有定义。
4.DOM中创建节点的方法
创建元素节点
document.createElement(' ')
创建文本节点
document.createTextNode(' ')
创建注释节点
document.createComment(' ')
创建文档碎片节点
document.createDocumentFragment('')
5.DOM中插入节点
ParentNode.appendChild()
首先要有选择一个父节点,小括号里填写要插入的节点,会把节点插入到父节点的最后一位
一个节点只能插入到一个地方,再次插入这个节点之前插入的就会消失
ParentNode.insertBefore(a,b)
在一个父节点内,把a节点插入到已知的b节点前面。
不一定非要插入自己创建的节点,已知的节点也可以使用插入调换位置
6.DOM中删除节点
ParentNode.removeChild()
父节点删除掉自己的节点并返回出去。
Child.remove()
直接销毁自身节点,连同自身的子节点一起删除。
返回undefined。
Node.replaceChild(new, origin)
替换一个节点,第一个填写新节点(new),第二个填写源节点(origin)(要替换的节点)。
可以查看,添加,覆盖HTML中的数据,
例如:
文字
控制台测试:
分别是对数据的查看,修改,覆盖。
如果添加的是元素节点的话,浏览器也会正常解释执行。
innerText(老版本火狐不兼容) && textContent(老版本IE不支持)
直接取出元素中的文本元素,赋值的话也可以覆盖源内容。
文字
121
执行 div.innerText 或者 div.textContent
输出:‘’文字 123‘’
Element.setAttribute
给一个元素节点设置属性(设置的新属性将会覆盖原来的属性)
例如:
文字
121
此时的 div 有两个属性,id为demo, class为test。
Element.getAttribute
获取元素节点的属性值。
结合博客园观看
小总结:
1、获取dom节点常用的方法:
getElementById('idName'); 只能id用
getElementsByTagName(''); 都能用,无兼容
getElementsByClassName(''); 都能用, IE8及以下不兼容
2、document.body => body
document.head => head
document.documentElement => html
以上内容的简单实践:
1、模仿实现chldren方法
//重写children Element.prototype.retChild = function(){ var child = this.childNodes, len = child.length, obj = { 'length' : 0, 'push' : Array.prototype.push } for(var i = 0; i < len; i++ ) { if(child[i].nodeType == 1){ obj.push(child[i]); } } return obj; }
Element.prototype.retChildren = function(){ var arrObj = { length: 0, push: Array.prototype.push } for(var node = this.firstChild; node; node = node.nextSibling){ if(node.nodeType == 1){ arrObj.push(node); } } return arrObj; }
2、封装函数,返回元素e的第n层祖先元素节点
Element.prototype.findIndexParent = function (n){ var ret = this.parentNode? this.parentNode : this; while(--n) { if(!ret.parentNode) { return ret; } ret = ret.parentNode; } return ret; }
3、封装函数,返回元素e的第n个兄弟节点,n为正,返回后面的兄弟节点,n为负,返回前面的,n为0,返回自己
// 封装函数,返回元素e的第n个兄弟节点,n为正,返回后面的兄弟节点,n为负,返回前面的,n为0,返回自己 Element.prototype.retIndexSibling = function (n) { var ret = this; // n === 0 if(n === 0) { return this; } // n !=== 0 while(n) { ret = n > 0? ret.nextSibling : ret.previousSibling; // 没有n个兄弟元素节点,则返回本身 if(!ret) { return this; } ret.nodeType === 1 && n > 0 && n--; ret.nodeType === 1 && n < 0 && n++; } return ret; }
4、请编写一段JavaScript脚本生成下面这段DOM结构。要求:使用标准的DOM方法或属性。提示 dom.className 可以读写class
text
// 创建div标签 且添加属性 var oDiv = document.createElement('div'); oDiv.className = 'example'; // 创建p标签 且添加属性 填充内容 var oP = document.createElement('p'); oP.className = 'slogan'; oP.innerHTML = 'text'; // 按顺序插入 oDiv.appendChild(oP); document.body.appendChild(oDiv);
5、封装函数insertAfter();功能类似insertBefore();提示:可忽略老版本浏览器,直接在Element.prototype上编程
//封装insertAfter() Element.prototype.insertAfter = function(targetNode, afterNode){ var nextSib = afterNode.nextElementSibling;
//如果父节点没有子元素或afterNode不存在的容错处理 if(this.children.length <= 1 || !nextSib){ this.appendChild(afterNode); }else { this.insertBefore(targetNode, nextSib); } }
6、封装remove(); 使得child.remove()直接可以销毁自身
Element.prototype.remove = function (){ // 像那些属性节点,注释节点,文本节点等等根本不可能做父节点,所以可以说parentNode返回的一般都是父元素节点 var definedParent = this.parentNode; definedParent.removeChild(this); }
7、将目标节点内部的节点顺序逆序。
eg:
// 将所有子元素逆序 Element.prototype.reverseChildren = function () { var children = this.children; var len = children.length; for(var i = 0; i < len; i++) { this.insertBefore(children[i], children[len - i - 1]); this.insertBefore(children[len - i - 1], children[i]); } }
8、parentElement 返回父级 元素节点(IE不兼容), 个人直接用node.parentNode就可以了,感觉除了元素节点外,其他类型节点都不适合做父节点
9、childElementCount (IE不兼容), 我们直接用node.children.length代替他即可解决不兼容问题
10、firstElementChild 返回第一个子级 元素节点(IE不兼容),我们用node.children[0]即可
11、lastElementChild 返回最后一个子级 元素节点(IE不兼容), 我们用直接返回node.dhildren的最后一个元素就可
12、nextElementSibling 返回后一个兄弟 元素节点(IE不兼容),js封装
// 返回后一个兄弟 元素节点 Element.prototype.nextEleSibling = function () { // 利用for循环的赋初值, 判断, 调整, 循环 这四种特性 for(var ret = this.nextSibling; ret && ret.nodeType !== 1; ret = ret.nextSibling) {} return ret; }
13、previousElementSibling 返回前一个兄弟 元素节点(IE不兼容), js封装, 原理同上
// 返回前一个兄弟 元素节点 Element.prototype.nextEleSibling = function () { // 利用for循环的赋初值, 判断, 调整, 循环 这四种特性 for(var ret = this.previousSibling; ret && ret.nodeType !== 1; ret = ret.previousSibling) {} return ret; }