定义
dom定义了表示和修改文档所需的方法。dom对象即为宿主对象,由浏览器厂商定义,用来操作html和xml功能的一类对象的集合。也有人称dom是对html以及xml的标准编程接口。
document 方法
document 代表整个文档
获取标签
// id IE8以下id不区分大小写 也返回name='id' 的元素
document.getElementById(‘id’)
// 标签名
document.getElementsTagName('div')
// 类名 ie9以下没有
document.getElementsClassName()
// 标签name属性 `<div name="hh"></div>`
document.getElementsByName(‘hh’)
// css选择器 ie8以下没有 选出的元素不是实时的(动态移除该元素后 选出的该元素还在)
document.querySelector()
// css选择器 ie8以下没有
document.querySelectorAll()
document.getElementsByTagName('*')
;//选择所有标签
创建节点
// 创建元素节点
document.createElement('div');
// 创建文本节点
document.createTextNode('文本节点内容');
// 创建注释节点
document.createComment('注释节点内容');
// 创建DocumentFragment(文档碎片)节点
document.createDocumentFragment();
插入节点
parentNode.appendChild(); //剪切操作
var div = document.createElement('div');
document.body.appendChild(div);// 把div插入body的底部
parentNode.insertBefore(a,b);// 一定要父级调用
// html
<div>
<span></span>
</div>
//js
var div = document.getElementsByTagName('div')[0],
span = div.getElementsByTagName('span')[0],
text = document.createElement('div');
div.insertBefore(text,span);// 在div下面 span 之前插入text
删除节点
parent.removeChild();
child.remove();
//html 同上
div.removeChild(span);//移除div下面的span 返回span 没有销毁,相当于剪切出来
div.remove(); // 移除div 返回undefined
替换节点
parent.replaceChild(new,origin);//拿 new 替换 origin 返回origin
//html 同上
div.replaceChild(text,span);
Element 节点一些属性 方法
innerHTML 获取节点的html结构 可读写
innerText(火狐不兼容)/textContent(老版本IE不好使) 获取节点的文本内容 可读写
setAttribute(‘id’,‘idName’);//设置节点属性
getAttribute(‘id’);//获取节点属性
节点树
遍历节点树 (文本节点 元素节点 注释节点 )
parentNode 父节点
childNodes 子节点们
firstChild 第一个子节点
lastChild 最后一个子节点
nextSibling 后一个兄弟节点
previousSibling 前一个兄弟节点
遍历元素节点树
parentElement 返回当前节点的父节点 (IE9不兼容)
children 只返回当前节点的子节点
node.childElementCount === node.children.length 当前元素节点的子元素个数(IE9不兼容)
firstElementChild 返回第一个元素子节点(IE9不兼容)
lastElementChild 返回最后一个元素子节点(IE9不兼容)
nextElementSibling 返回后面一个兄弟元素 (IE9不兼容)
previousElementSilbling 返回前面一个兄弟元素 (IE9不兼容)
节点的四个属性
nodeName 节点名称 ,只读
nodeValue 文本节点或Comment(注释)节点的文本内容 可读写
nodeType 节点类型 ,只读
元素节点 1,属性节点 2,文本节点 3,注释节点 8 ,document 9,DocumentFragment 11
//html
<div id="div" class="class"></div>
//js
var div = document.getElementsByClassName('class')[0];
div.attributes;//{0: id,1:class,length:2}
div.attributes[0];// id="div"
div.attributes[0].nodeType;// 2 //属性节点
div.attributes[0].value;// div
div.attributes[0].name;// id
attributes Element节点的属性集合
节点方法 node.hasChildNodes()
判断有没有子节点(所有类型节点) node.hasChildNodes()
document 与 Document HTMLDocument
document 是文档节点 对象
Document 是构造函数(不能new Document ,系统自己用)
document 不是 Document 直接构造出来的
document 是 HTMLDocument 构造出来的
Document.prototype.abc = "abc"
HtmlDocument.prototype.bcd = "bcd "
document.abc;// "abc"
document.bcd;// "bcd"
//-----------
HTMLDocument.prototype = {
...
__porto__ : Document.prototype
}
document.prototype = {
...
__porto__ : HTMLDocument.prototype
}
DOM树
继承关系 向上继承
- Node
- Document
- HTMLDocument
- document
- XMLDocument
- …
- HTMLDocument
- CharacterData
- Element
- HTMLElement(HTML节点)
- HTMLHeadElement
- HTMLBodyElement
- HTMLDivElement
- …
- XMLElement
- …
- HTMLElement(HTML节点)
- Attr
- Document
HTMLBodyElement.prototype.abc = "abc"
var body = document.getElementsByTagName('body')[0];
var head = document.getElementsByTagName('head')[0];
body.abc;//"abc"
head.abc;//undefined
Node.__proto__; //EventTarget()
Node.__proto__.proto__;//Object.Prototype (最终原型对象)
getElementById 方法定义在 Document.peototype 上
getElementsByName 方法定义在 HTMLDocument.peototype 上 即XML节点不能调用该方法
getElementsByTagName 方法定义在 Document.peototype 和 Element.prototype 上
// html
<div>
<span></span>
</div>
//js
var div = document.getElementsByTagName('div')[0];
var span = div.getElementsByTagName('span')[0];
HTMLDocument.peototype 定义了一些常用的属性 body,head分别指代文档中的 <body><head>
标签
Document.prototype 上定义了 documentElement 属性 指代文档的根元素,在Html文档中,总是指代<html>
元素
document.body;// body标签
document.documentElement;// html标签
getElementsByClassName/queruSelector/queruSelectorAll 在 Document.prototype 和 Elemenet.prototype 上都有定义
题目
遍历元素节点树(在原型链上)
题意:1,给父节点,遍历所有子节点
2,打印层级结构(向下)
1,给父节点,遍历所有子节点
Element.prototype.tree = function(){
return this.childNodes
}
// document.body.tree()
2,打印层级结构(线下)
// 包含所有类型节点
Element.prototype.tree2 = function(){
var nodes = this.childNodes,
obj = {
name: this,
length: 0,
push: Array.prototype.push,
splice: Array.prototype.splice
}
treee(nodes,obj)
function treee(nodes,obj){
var len = nodes.length;
for(var i = 0;i < len; i++){
if(nodes[i].nodeType == 1){ //元素节点
if(nodes[i].childNodes){
var obj1 = {
name:nodes[i],
length:0,
push: Array.prototype.push,
splice: Array.prototype.splice
}
obj.push(obj1)
treee(nodes[i].childNodes,obj1)
}
}else{
obj.push(nodes[i])
}
}
}
return obj
}
// document.body.tree2()
// 只包含元素节点
Element.prototype.tree3 = function(){
var nodes = this.childNodes,
obj = {
name: this,
length: 0,
push: Array.prototype.push,
splice: Array.prototype.splice
}
treee(nodes,obj)
function treee(nodes,obj){
var len = nodes.length;
for(var i = 0;i < len; i++){
if(nodes[i].nodeType == 1){ //元素节点
if(nodes[i].childNodes){
var obj1 = {
name:nodes[i],
length:0,
push: Array.prototype.push,
splice: Array.prototype.splice
}
obj.push(obj1)
treee(nodes[i].childNodes,obj1)
}else{
obj.push(nodes[i])
}
}
}
}
return obj
}
// document.body.tree3()
封装函数,返回元素e的第n成祖先元素节点
function parents(e,n){
n = n || 1;
for(var i = 0; i < n; i++){
e = e ? e.parentElement : e
}
return e
}
封装函数,返回元素e的第n个兄弟节点 n为正,返回后面的兄弟元素节点,n为负,返回前面的兄弟节点 0 返回本身
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div>
<span>1</span>
<span>2</span>
<span>3</span>
</div>
<script>
var span = document.getElementsByTagName('span')[1],
div = document.getElementsByTagName('div')[0];
// 不兼容 IE9 及以下版本
function sibling(node,n){
n = n || 0,
len = Math.abs(n); //返回绝对值
for(var i = 0; i < len; i++){
if(node){
node = n > 0 ? node.nextElementSibling : node.previousElementSibling
}
}
return node
}
// console.log(sibling(span,1))
// 兼容 IE9 及以下版本
function siblingCompatibility(node,n){
n = n || 0,
len = Math.abs(n); //返回绝对值
for(var i = 0; i < len; i++){
if(node){
// node = n > 0 ? nextPrev(node.nextSibling,'next') : nextPrev(node.previousSibling,'prev')
// 或
if(n > 0){
node = node.nextElementSibling ? node.nextElementSibling : nextPrev(node.nextSibling,'next')
}else{
node = node.previousElementSibling ? node.previousElementSibling : nextPrev(node.previousSibling,'prev')
}
}
}
function nextPrev(node,type){
if(node.nodeType != 1 && node != null){
node = type == 'next' ? nextPrev(node.nextSibling,'next') : nextPrev(node.previousSibling,'prev')
}
return node
}
return node
}
console.log(siblingCompatibility(span,0))
或
function siblingCompatibility(node,n){
n = n || 0,
len = Math.abs(n); //返回绝对值
for(var i = 0; i < len; i++){
if(node){
if(n > 0){
if(node.nextElementSibling){
node = node.nextElementSibling
}else{
for(node = node.nextSibling; node && node.nodeType != 1; node = node.nextSibling);
}
}else{
if(node.previousElementSibling){
node = node.previousElementSibling
}else{
for(node = node.previousSibling; node && node.nodeType != 1; node = node.previousSibling);
}
}
}
}
return node
}
console.log(siblingCompatibility(span,3))
</script>
</body>
</html>
编辑函数 ,封装 myChildren功能,解决以前部分浏览器的兼容性问题,模仿children功能,不可用children属性
Element.prototype.myChildren = function(){
var node = this.childNodes,
len = node .length,
obj = {
length: 0,
push: Array.prototype.push,
splice: Array.prototype.splice
}
for(var i = 0;i<len ;i++){
node[i].nodeType == 1 ? obj.push(node[i]):""
}
return obj
}
封装自己的hasChildNodes()方法,不可用children属性
判断 节点有没有该子节点
function myHasChildNodes(father,son){
var nodes = father.childNodes,
len = nodes.length;
for(var i =0; i<len; i++){
if(nodes[i] == son){
return true
}
}
return false
}
console.log(myHasChildNodes(div,span))
封装insertAfter() 功能类似insertBefore();
Element.prototype.insertAfter = function(target,after){
var before = after.nextElementSibling || next(after);
if(before){
this.insertBefore(target,before)
}else{
this.appendChild(target)
}
function next(after){
var _next = after.nextSibling;
if(_next == null || _next.nodeType == 1){
return _next
}else{
return next(_next)
}
}
}