两个节点之间可能存在哪些关系?
父子节点,兄弟节点,后代节点,祖先节点。
通常子节点在childNodes属性里,以及attributes属性里。
通常情况是,文本节点没有子节点。document节点没有父节点。
如何在节点之间任意移动?
要想移动,必先找到该节点。
首先查找元素节点有两种方式,一种是getElementById,另一种是getElementsByName。
第一种就直接返回某个节点,第二种返回的是节点列表。 这两种查找方式很大程度上忽略了document结构。
<!
DOCTYPE html
>
<
html
>
<
head
>
<
title
>Hacking JavsScript
</
title
>
</
head
>
<
body
>
<
h1
>Hello world!
</
h1
>
<
p
>I am a JavaScript hacker!
</
p
>
<
div
id
="p1"
>
<
p
>I am hacker too!
</
p
>
<
p
>I am hacker three!
</
p
>
</
div
>
<
script
type
="text/JavaScript"
>
var
x
=
document.getElementsByTagName(
'
h1
'
)[
0
];
var
y
=
document.getElementsByTagName(
'
p
'
)[
0
];
x.parentNode.insertBefore(y, x);
var
p1
=
document.getElementById(
'
p1
'
).getElementsByTagName(
"
p
"
);
console.log(p1);
</
script
>
</
body
>
</
html
>
这段代码,尤其改变了两个节点的位置了。以及id和TagName获取方式
DOM操作——怎样添加、移除、移动、复制、创建和查找节点,以及获取节点信息。
1.查找节点是个大事情,除了id和TagName查找这种忽略文档结构的查找,还有依赖文档结构的查找,需要用到节点的五个属性和两个节点列表。
<!
DOCTYPE html
>
<
html
>
<
head
>
<
title
>Hacking JavsScript
</
title
>
</
head
>
<
body
>
<
table
>
<
tbody
>
<
tr
id
="first_tr"
><
td
class
="number"
><
input
/></
td
><
td
id
="second_td"
class
="description"
>Spicy roast beef
</
td
><
td
class
="extra"
>With our own mix of herbs and spices
</
td
><
td
class
="empty"
>home made
</
td
></
tr
>
</
tbody
>
</
table
>
<
script
type
="text/JavaScript"
>
var
firs_tr
=
document.getElementById(
'
first_tr
'
);
var
second_td
=
document.getElementsByTagName(
'
td
'
)[
1
];
console.log(firs_tr.firstChild);
//
console.log(firs_tr.firstElementChild);
console.log(firs_tr.lastChild);
//
console.log(firs_tr.lastElementChild);
console.log(second_td.parentNode);
console.log(second_td.previousSibling);
console.log(second_td.nextSibling);
console.log(firs_tr.childNodes);
console.log(firs_tr.children);
</
script
>
</
body
>
</
html
>
如上所示, 五个属性是parentNode,firstChild,lastChild,previousSibling和nextSibling。两个节点列表是childNodes和children。
其中,用得比较多的是parentNode,firstChild,lastChild,children。
要注意的是,上面tr和td元素代码之间有空格的话,firstChild就是文本节点了,而不是<td class="number">。这里就涉及到浏览器兼容了,IE是忽略代码之间的空格,而Firefox不忽略
children的节点列表都是元素节点,而childNodes的节点列表包括文本节点和元素节点。当然children和childNodes都不包含属性节点。属性节点通过节点的attributes属性取得。
2.删除,移除节点
这个需要parentNode属性,也就是父节点。父节点是好东西,你在或者不在,父节点都在。尤其是对未来生成的元素绑定事件,更需要父节点。jQuery经常干这事。
删除也需要父节点。
<!DOCTYPE html>
<html>
<head>
<title>Hacking JavsScript</title>
</head>
<body>
<table>
<tbody>
<tr id=
"
first_tr
"><td
class=
"
number
"><input /></td><td id=
"
second_td
"
class=
"
description
">Spicy roast beef</td><td
class=
"
extra
">With our own mix
of herbs
and spices</td><td
class=
"
empty
">home made</td></tr>
</tbody>
</table>
<script
type=
"
text/JavaScript
">
var firs_tr = document.getElementById(
'
first_tr
');
var second_td = document.getElementsByTagName(
'
td
')[
1];
second_td.parentNode.removeChild(second_td);
</script>
</body>
</html>
还有个replaceChild(newNode, oldNode)函数,返回的是oldNode节点。函数的用处是把newNode替换oldNode,如果newNode存在文档中,首先移除newNode。
移除子节点,两个思路,
While(x.childNodes[0]){x.removeChild(x.childNodes[0])};
另一个是
x.innerHTML = ‘’;
3.获取节点信息
nodeName
属性用来展示节点的名称。比如文本节点的名称是
#text
,文档节点的名称是
#document
,元素节点名称是大写字母的
HTML
元素标签名。
nodevalue属性对于文本节点,展示文本内容。对于属性节点,展示属性值。对于文档节点和元素节点不可用。
nodeType属性对于Element元素节点,值是1.对于Attribute属性节点的值是2,Text文本节点的属性值是3,Comment注释值是8,Document文档节点属性值是9。
4.增加节点
增加节点有两个方法,需要父节点。
第一个是appenChild方法。
<!
DOCTYPE html
>
<
html
>
<
head
>
<
title
>Hacking JavsScript
</
title
>
</
head
>
<
body
>
<
table
>
<
tbody
>
<
tr
id
="first_tr"
><
td
id
="first_td"
class
="number"
><
input
value
="first td"
/></
td
><
td
id
="second_td"
class
="description"
>Spicy roast beef
</
td
><
td
class
="extra"
>With our own mix of herbs and spices
</
td
><
td
class
="empty"
>home made
</
td
></
tr
>
<
tr
id
="second_tr"
></
tr
>
</
tbody
>
</
table
>
<
script
type
="text/JavaScript"
>
var
firs_tr
=
document.getElementById(
'
first_tr
'
);
var
second_tr
=
document.getElementById(
'
second_tr
'
);
var
first_td
=
document.getElementById(
'
first_tr
'
).getElementsByTagName(
'
td
'
)[
0
];
var
second_td
=
document.getElementById(
'
first_tr
'
).getElementsByTagName(
'
td
'
)[
1
];
second_tr.appendChild(second_td);
//
first_td.parentNode.appendChild(first_td);
if
(firs_tr
==
first_td.parentNode){
firs_tr.appendChild(first_td);
}
</
script
>
</
body
>
</
html
>
如上所示,appendChild方法让你添加一个节点并使其成为某个元素的最后一个子节点,如果该节点存在于文档中,它会从当前位置移除。
第二个是insertBefore方法。
<!
DOCTYPE html
>
<
html
>
<
head
>
<
title
>Hacking JavsScript
</
title
>
</
head
>
<
body
>
<
table
>
<
tbody
>
<
tr
id
="first_tr"
><
td
id
="first_td"
class
="number"
><
input
value
="first td"
/></
td
><
td
id
="second_td"
class
="description"
>Spicy roast beef
</
td
><
td
class
="extra"
>With our own mix of herbs and spices
</
td
><
td
class
="empty"
>home made
</
td
></
tr
>
<
tr
id
="second_tr"
></
tr
>
</
tbody
>
</
table
>
<
script
type
="text/JavaScript"
>
var
firs_tr
=
document.getElementById(
'
first_tr
'
);
var
second_tr
=
document.getElementById(
'
second_tr
'
);
var
first_td
=
document.getElementById(
'
first_tr
'
).getElementsByTagName(
'
td
'
)[
0
];
var
second_td
=
document.getElementById(
'
first_tr
'
).getElementsByTagName(
'
td
'
)[
1
];
var
thrid_td
=
document.getElementById(
'
first_tr
'
).getElementsByTagName(
'
td
'
)[
2
];
first_td.parentNode.insertBefore(second_td, first_td);
second_tr.insertBefore(thrid_td,
null
);
</
script
>
</
body
>
</
html
>
这个就是插在某个节点前面。如果第二个参数为null,则跟appendChild效果一样。
注意:appendChild和insertBefore都返回被插入的节点。
5.创建节点
Element节点的创建函数是crateElement(),
文本节点的创建函数是createTextNode(),两个一起用就是,
var p_element = document.createElement('p');
var text = document.createTextNode('This is a text');
p_element.appendChild(text);
创建好元素后,我们要把它放到body里面
document.body.appendChild(p_element);
再弄个attribute属性节点,它的创建函数是setAttribute(),
p_element.setAttribute('value','this is p');