JS DOM节点

Node类型

JS中的所有节点都继承了Node节点的属性和方法,均有一个表示节点类型的nodeType属性,这些属性的值可以取为下列常量或者对应数值;

node.nodeType   // 1;
node.nodeValue  // null
node.ownerDocument  // #document
Node.ELEMENT_NODE                    --->  1   --->  元素节点                    
Node.ATTRIBUTE_NODE                 --->  2   --->  属性节点
Node.TEXT_NODE                      --->  3   --->  文本节点
Node.CDATA_SECTION_NODE             --->  4   --->  文档中的CDATA区段节点
Node.ENTITY_REFERENCE_NODE          --->  5   --->  实体引用节点
Node.ENTITY_NODE                    --->  6   --->  实体节点
Node.PROCESSING_INTRODUCTION_NODE   --->  7   --->  处理指令节点
Node.COMMET_NODE                    --->  8   --->  注释节点
Node.DOCUMENT_NODE                  --->  9   --->  文档节点
Node.DOCUMENT_TYPE_NODE             --->  10  --->  文档类型节点
Node.DOCUMENT_FRAGEMENT_NODE        --->  11  --->  文档片段节点
Node.NOTATION_NODE                  --->  12  --->  DTD声明节点

节点都有nodeName和nodeValue属性;对于元素节点nodeName保存的是元素的标签名,元素节点的nodeValue的值始终为null;

每个节点都需要一个childNodes,保存着一个的类数组对象NodeList,返回的是基于DOM结构动态执行查询的结果;另外也可以通过item(index)方法访问;node.childNodes.item(index);

节点的常用属性: childNodes/ parentNode/ previousSibling/ nextSibling/ firstChild/ lastChild/ ownerDocument指向整个文档的文档节点/
节点的常用方法
node.hasChildNodes()无参方法,有子节点时返回true,否则为false;
node.appendChild()方法返回新增节点,用于向childNodes列表末尾添加一个节点;
node.insertBefore(newNode, referNode): 接受两个参数,分别为要插入的节点和作为参照的节点;插入节点将变为参考节点的前一个兄弟节点; 同时会返回新插入的节点;如果参考节点为null,则insertBefore()与appendChild()作用相同;如果新节点存在,那么新节点的位置会更新到当前位置;
node.replaceChild(newNode, replaceNode); 接受两个参数新节点和被替换节点,返回的是被替换节点;
node.removeChild(removedNode): 移除节点;虽然移除的节点已经不在文档树中,但其仍然属于文档所有;

所有类型节点共有的两个方法:
1、node.cloneNode(boolean)方法接收一个布尔值作为参数,true则为深拷贝,返回的是节点的副本,包括其子节点树;该副本是一个孤立节点,属于文档所有,但是需要调用上述方法才能将其加入到文档树中;cloneNode()方法不会复制DOM对象的JS属性,但是IE会复制事件处理程序,因此需要在拷贝时解除绑定的事件处理程序;
2、node.normalize():该方法仅可以处理文档树中的文档节点,如果有两个相邻的节点,调用该方法会将这两个节点合并;如果文本节点为空,调用该方法会删除空文本节点;

var wrapper = document.createElement('div');
textNode1 = document.createTextNode('text1');
textNode2 = document.createTextNode('text2');
wrapper.appendChild(textNode1);
wrapper.appendChild(textNode2);
wrapper.childNodes.length;  // 2
wrapper.normalize();
wrapper.childNodes.length;  // 1

IE<9的浏览器版本中不会对空字符串创建文本节点,因此下例中node.childNodes.length返回4,其他浏览器返回9;

    <ul class="list">
        <li>HTML</li>
        <li>CSS</li>
        <li>JS</li>
        <li>JAVA</li>
    </ul>

这里写图片描述


Document类型

document对象表示整个HTML页面,是HTMLDocument的实例;通过document.documentElement可以直接访问到<html>元素;document.body可以直接访问到<body>元素;这两个方法所有的浏览器都支持;另外,还有一个doctype属性不同的浏览器实现之间存在很大差别;

window.document instanceof window.HTMLDocument  // true;
node.nodeType   // 9
node.nodeName   // #document
node.nodeValue  // null
node.parentNode // null
node.ownerDocument  //null

访问文档属性的方法:
document.domain是可写的,仅可以将其由tight域名改为loose域名,这样一般用于同一父级域名下不同框架之间的通信;

document.title
document.URL        // 页面完整URL "https://www.baidu.com/"
document.domain     // 页面域名 "www.baidu.com"
document.referrer   // 链接到当前页面的URL

查找元素: document.getElementById() 和 document.getElementByTagName();
1、getElementById()方法对传入的参数区分大小写,查找失败返回null;IE8及以下版本则不区分ID大小写;

IE中关于getElementById()的问题
在浏览器IE7及较低版本的IE浏览器中,如果存在表单元素(input/ button/ select/ textarea)的name特性等于目标元素的ID,并且该表单元素位于目标元素前,那么在这些浏览器中会返回表单元素而不是目标元素;

<input type="text" name="targetElement" value="name">
<div id="targetElement">hello World</div>

IE7及以下版本中返回input元素;其他浏览器正常返回目标元素;

2、getElementsByTagName()方法返回一个HTMLCollection对象,这也是一个类数组对象;可以传入‘*’获取文档中所有元素;除了document有该方法外,元素也有该方法;

3、一些特殊属性:document.anchors获取所有带name属性的<a>元素; document.forms包含文档中所有的<form>元素;document.images获取所有<img>元素;document.links包含文档中所有带href属性的<a>元素;

DOM一致性检测
使用document.implementation具有hasFeature()方法,接受两个参数分别表示DOM功能及相应的版本号,返回值为Boolean类型;
建议同时使用浏览器能力检测;


Element类型

Element类型提供了对元素标签名、子节点及特性的访问;nodeType为1,node.nodeName === node.tagName;
在HTML中标签名是大写形式表示,在XML中则与XML文档中的命名一样;
2、关于属性设置的方法:node.getAttribute()/ setAttribute()/ removeAttribute(),属性名称不分大小写,HTML5规范中自定义的属性名需要加入data-前缀
3、document.createElement用于创建元素,IE中则可以使用createElement(),不过参数不同,它接收的参数为为包含属性的完整标签;

createElement("<div id=\"myDiv\" class=\"myClass\"></div>"

IE8以下的版本(不包含IE8)创建元素的一些兼容性问题: 动态创建的<iframe>元素不能设置其name属性,因此需要创建时同时指定这些属性;动态创建的<input>不可以通过reset()方法重新设置;


Attr类型

创建属性节点可以使用document.createAttribute()方法,传入的是属性名,设置属性可以使用attr.value;该节点具有三个属性name, value, specified(用于确认一个属性是默认属性还是代码指定的);


Text类型

TextNode的parentNode为Element结点,没有子节点;

nodeType    // 3
nodeName    // '#text'
nodeValue   // 对应的包含文本

// 文本节点处理方法
appendData(text);
deleteData(offset, count);
insertData(offset, text);
replaceData(offset, count, text)
splitText(text);    //分割文本节点是从中提取数据的常用的DOM解析技术;
subStringData(offset, count)

Comment

注释节点,没有子节点;可以通过nodeValue或者data属性取得该内容。可以通过document.createComment(text)创建注释节点;

nodeType    // 8
nodeName    // "#comment"
nodeValue   // 注释内容
// html
<div id="cNode"><!-- this is a comment --></div>
// JS
var node = document.getElementById('cNode');
var comment = node.firstChild;
console.log(comment.data === comment.nodeValue);

DocumentType类型

没有子节点;

nodeType    // 10
nodeName    // docType
nodeValue   // null
parentNode  // Document

DocumentFragment类型
创建文档片段类型可以使用document.createDocumentFragment()方法;该类型继承了Node的所有方法;文档片段本身不会成为文档树的一部分;
使用文档片段的方式可以避免浏览器的反复渲染,仅进行一次渲染更新;

nodeType    //  11
nodeName    // "#document-fragment"
nodeValue   // null
parentNode  // null

这里写图片描述

上例中为了向<ul>添加三个<li>子元素,先创建一个文档片段节点,然后分别创建li节点并将其添加到文档片段节点中,然后将该列表添加到文档片段中;最后将文档片段添加到ul中;此时文档片段中的所有子节点都被删除并转移到<ul中;

创建动态脚本存在一定的兼容性问题,在IE中<script>元素为一个特殊元素,无法通过DOM访问其子节点,因此无法使用appendChild()属性,可以用text属性包好相应的脚本代替;

var script = document.createElement('script');
script.type = 'text/javascript';
var code = "function f() {console.log('hello');}";
try {
    script.appendChild(document.createTextNode(code));
} catch (ex) {
    script.text = code;
}

同样地,创建动态样式也具有相似的问题,可以使用下面的代码实现兼容

var style = document.createElement('style');
style.type = 'text/css';
try {
    style.appendChild(document.createTextNode("body{background-color:red}"));
} catch (ex) {
    style.stylesheet.cssText = "body{background-color:red}";
}

创建表格

DOM中定义了专门简化表格相关的一些属性和方法,tBodied/ tFoot/ tHead/ rows/ caption/ createTHead()/ createTFoot()/ createCaption()/ deleteTHead()/ deleteTFoot()/ deleteCaption()/ deleteRow(index)/ insertRow(index)/ rows/ deleteRow(index)/ insertRow(index)/ cells/ deleteCell(index)/ insertCell(index)。

/* 创建表格 */
// 创建table
var table = document.createElement("table");
table.border = 1;
table.width = "100%";

// 创建tbody
var tbody = document.createElement("tbody");
table.appendChild(tbody);

// 创建一行
tbody.insertRow(0);
tbody.rows[0].insertCell(0).appendChild(document.createTextNode("(1,1)"));
tbody.rows[0].insertCell(1).appendChild(document.createTextNode("(1,2)"));

// 创建另一行
tbody.insertRow(1);
tbody.rows[1].insertCell(0).appendChild(document.createTextNode("(2,1)"));
tbody.rows[1].insertCell(1).appendChild(document.createTextNode("(2,2)"));

document.body.appendChild(table);

NodeList/ NamedNodeMap/ HTMLCollection会随着文档内容的更新动态更新
这里写图片描述

这里首先获取了HTMLCollection动态对象,每次动态地插入div元素到文档中后,HTMLCollection列表对象都会更新,那么每次循环后变量i和divs.length就会同时更新,那么这就是一个死循环;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Neil-

你们的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值