1、DOM相关
1.1 基础概念
在一个html文档(树)中,所有的东西都是Node节点。Node是最基础的基类,有子类Document、Element、CharacterData(text、comment)。
其中Document代表一个html文档,是最顶层节点,js中可以用window.document(document)引用到。
html标签代表的是最顶层的元素element(HTMLHtmlElement),js中可以用document.documentElement引用到。
Node类定义了一些基本的属性和方法,如childNodes、nodeType、nodeName、nodeValue。
一个document节点,他的childNodes通常至少包括一个顶层htmlelement(html标签),还可以有Doctype节点、comment注释节点。
一个顶层html element(<html>),通常至少包括一个head element(<head> HTMLHeadElement)、body(<body> HTMLBodyElement),这两个element可以用document.head合document.body引用到
考虑如下代码:
<!DOCTYPE html>
<!-- this is a comment -->
<html>
<head>
<title>test DOM 2(www.asarea.me)</title>
<script type="text/javascript">
window.onload = function() {
//一个html页面所有都是Node,Node是最上层的基类
console.log(document, document.nodeType, document.nodeName, document.nodeValue);
var nodes = document.childNodes;
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
console.log(node, node.nodeType, node.nodeName, node.nodeValue);
};
}
</script>
</head>
</html>
输出:
1.2 操作
1.2.1 获取element
Node对我们来说通常用处不大,我们通常需要直接操作的是Element。
一个Element是由一个tag加上一些属性组成。因此Element新增加了一些属性和方法,如tagName,children(只返回子elements),getAttribute等。
获取Element的方法,通常用到document的几个方法,
A、根据id:getElementById
B、根据name:getElementsByName
C、根据tag类型:getElementsByTagName
D、根据classname:getElementsByClassName
E、采用css选择器:querySelectorAll、querySelector(不同浏览器有兼容性问题,可以采用jquery封装的sizzle,支持强大的css选择器语法同时解决兼容性问题)。
考虑如下代码:
输出:<html>
<head>
<title>test query(www.asarea.me)</title>
<script type="text/javascript">
window.onload = function() {
//为element分配id属性会自动定义一个id值的属性在window上,不是在document上
//尽量采用document.getElementById为不要采用window.**方式获取element
console.log(window.divA, document.divA);
console.log(window.divA === document.getElementById('divA'));
console.log('------------------');
console.log(document.getElementsByName('formA'));
console.log(document.getElementsByName('txtA'));
console.log('------------------');
console.log(document.getElementsByTagName('div'));
console.log(document.getElementsByTagName('span'));
console.log('------------------');
console.log(document.getElementsByClassName('left'));
console.log(document.getElementsByClassName('left right'));
console.log('------------------');
console.log(document.querySelectorAll('.left'));
console.log(document.querySelector('.left'));
console.log(document.querySelectorAll('*[id="divA"]'));
}
</script>
</head>
<body>
<div id='divA'>divA</div>
<div id='divB' class='left right'>divB</div>
<span id='spanA' class='left'>spanA</span>
<form name='formA' onsubmit='return false;'>
<input type='text' name='txtA'>
</form>
</body>
</html>
1.2.2 获取element属性
获取element属性的途径都是定义在Element中:
A、HtmlElement定义了一些标准的html属性,可以直接获取,如ele.id,ele.onclick等。属性值可以是字符串、布尔值、cssstyleDeclaration、function。
B、Element的getAttribute方法可以用来获取标准、非标准属性,但是属性值永远当做 字符串!!
C、非标准属性除了用getAttribute获取外,还可以用dataset属性来获取设置(前提是属性名必须是data-),这是html5中新增的
D、还有可以用attributes来获取,属性值也是当做字符串
考虑如下代码:
输出:<html>
<head>
<title>test attribute(www.asarea.me)</title>
<script type="text/javascript">
window.onload = function() {
var ele = document.getElementById('textA');
//取不到返回null,而非undefined
console.log(ele === null, ele === undefined);
//HtmlElement定义了一些标准的html属性,可以直接获取,属性值可以是字符串、布尔值、cssstyleDeclaration、function
console.log(ele.id, ele.required, ele.style, ele.onclick);
//getAttribute可以用来获取标准、非标准属性,属性值永远当做 字符串!!
console.log(ele.getAttribute('id'), ele.getAttribute('required'), ele.getAttribute('style'), ele.getAttribute('onclick'));
//非标准属性除了用getAttribute获取外,还可以用dataset属性来获取设置(前提是属性名必须是data-)
console.log(ele.getAttribute('data-test'), ele.dataset.test);
//还有可以用attributes来获取,属性值也是当做字符串
console.log(ele.attributes.id.value, ele.attributes.style.value, ele.attributes['data-test'].value);
}
</script>
</head>
<body>
<input type='text' id='textA' required data-test='test' style='width:100' onclick='alert("click");'></div>
</body>
</html>
1.2.3 获取、设置element内容
element内容可以有html源码格式,也可以是纯文本格式。
获取、设置element内容的方法有:
1、html源码格式,可以通过Element的innerHTML、outerHTML(带自身标签)获取&设置。
2、纯文本格式,可以通过Node的属性textContent,而IE只支持HTMLElement的innerText(innerText尝试保留一些格式)
考虑如下代码:
<html>
<head>
<title>test content(www.asarea.me)</title>
<script type="text/javascript">
window.onload = function() {
var ele = document.getElementById('divA');
//element的属性:innerHTML outerHTML
console.log(ele.innerHTML, ele.outerHTML);
console.log('------------------');
//node的属性textContent, IE的innerText(innerText尝试保留一些格式)
console.log(ele.textContent, ele.innerText);
console.log('------------------');
console.log(getTextContent(ele));
}
function getTextContent(ele) {
//如果是text类型
if(ele.nodeType === 3) {
return ele.nodeValue;
}
//否则递归找所有子node
else {
var s = '';
for (var i = 0; i < ele.childNodes.length; i++) {
s += getTextContent(ele.childNodes[i]);
}
return s;
}
}
</script>
</head>
<body>
<div id='divA'>
this is <p> paragraph. </p> this is <b>bold text</b>.
</div>
</body>
</html>
输出如下:
1.2.4 创建、复制、插入、替换、删除element
创建节点可以用document.createElement方法,传入标签名。也可以用document.createTextNode方法创建text纯文本节点。
复制节点可以用node.cloneNode方法,传入true代表深度复制。
插入节点用node.insertBefore或者node.appendChild方法。
替换节点用node.replaceChild方法。
删除节点用node.removeChild方法。
另外有一个叫片段的特殊node,可以作为一系列节点的暂时容器,然后将这个片段统一插入到某element下。
片段的创建方法:document.createDocumentFragment();
参考如下代码:
<html>
<head>
<title>test modify elements(www.asarea.me)</title>
<script type="text/javascript">
var createIndex = 0;
window.onload = function () {
addListener(document.getElementById('btnCreate'), 'click', onCreate);
addListener(document.getElementById('btnSort'), 'click', onSort);
}
function onCreate() {
createIndex++;
var newEle = document.createElement('div');
newEle.innerHTML = 'This is the ' + createIndex + ' created item. <button onclick="onDelete(this)">删除</button><button onclick="onReplace(this)">替换</button>';
var parent = document.getElementById('dynamicDiv');
parent.appendChild(newEle);
}
function onReplace(btn) {
var ele = btn.parentNode;
var newEle = document.createTextNode('This is replaced');
ele.parentNode.replaceChild(newEle, ele);
}
function onDelete(btn) {
var ele = btn.parentNode;
ele.parentNode.removeChild(ele);
}
function onSort() {
//片段器,是一个节点临时容器
var frag = document.createDocumentFragment();
var parent = document.getElementById('dynamicDiv');
//将子节点倒序加入片段器
while(parent.lastChild) {
frag.appendChild(parent.lastChild);
}
//再总体加入父容器
parent.appendChild(frag);
}
function addListener(obj, evt, handler) {
if(obj.addEventListener) {
obj.addEventListener(evt, handler);
}
else if(obj.attachEvent) {
obj.attachEvent('on' + evt, handler);
}
}
</script>
</head>
<body>
<div id='dynamicDiv'>
</div>
<button id='btnCreate'>创建</button>
<button id='btnSort'>倒序</button>
</body>
</html>
效果如下: