利用节点父子兄获取元素
节点的基本属性
nodeType(节点类型)
nodeName(节点名称)
nodeValue(节点值)
特点
元素节点 nodeType=1;
属性节点 nodeType=2;
文本节点 nodeType=3(文本节点包含文字,空格,换行)
节点层级
利用DOM树可以把节点划分为不同的层级关系,常见的是父子兄关系
1.父级节点
node.parentNode
//得到最近的父节点,找不到返回none
<body>
<div>
<div class="father">
<span class="son"></span>
</div>
</div>
<script>
var ele = document.querySelector('.son');
// var ele = document.getElementsByClassName("son");用这种写法不行
console.log(ele);
console.log(ele.parentNode);
</script>
</body>
2.子节点
2.1.获取所有的子节点,包括元素节点,文本节点等
parentNode.childNodes(标准)
//返回一个集合
2.2.获取所有的子元素节点
parentNode.children(非标准)
<body>
<ul>
<li>ul的li</li>
<li>ul的li</li>
<li>ul的li</li>
<li>ul的li</li>
<li>ul的li</li>
<li>ul的li</li>
</ul>
<ol>
<li>ol的li</li>
<li>ol的li</li>
<li>ol的li</li>
<li>ol的li</li>
<li>ol的li</li>
<li>ol的li</li>
</ol>
<script>
var ul = document.querySelector('ul');
//childs获取所有节点,包含文字空格等
var lis = ul.childNodes;
console.log(lis);//NodeList(13) [text, li, text, li, text, li, text, li, text, li, text, li, text]
console.log(lis[0].nodeType)//判断是否是元素节点
//2.获取所有的子元素节点
console.log(ul.children);//HTMLCollection(6) [li, li, li, li, li, li]
</script>
</body>
2.3.获取第一个子节点(所有节点)
parentNode.firstChild
2.4.获取最后一个节点(所有节点)
parentNode.lastChild
2.5.返回第一个子元素节点(IE9以上支持)
parentNode.firstElementChild
2.6.返回最后一个子元素节点(IE9以上支持)
parentNode.lastElementChild
<body>
<ol>
<li>第1个li</li>
<li>第2个li</li>
<li>第3个li</li>
<li>第3个li</li>
<li>第4个li</li>
</ol>
<script>
var ol = document.querySelector('ol');
console.log(ol.firstChild);//#text
console.log(ol.lastChild);//#text
console.log(ol.firstElementChild);//<li>第1个li</li>
console.log(ol.lastElementChild);//<li>第4个li</li>
</script>
</body>
显示或隐藏下拉菜单(有误)
<style>
li {
list-style: none;
}
.outer {
width: 800px;
height: 30px;
background-color: pink;
margin: 0 auto;
}
.outer li {
float: left;
width: 150px;
border: 1px solid blue;
text-align: center;
margin-right: 5px;
}
.outer li:hover {
background-color: green;
}
.inner {
display: none;
}
.inner li {
float: none;
width: 100px;
height: 40px;
background-color: skyblue;
margin: 0 auto;
}
</style>
<body>
<ul class="outer">
<li>微博
<ul class="inner">
<li>点赞</li>
<li>@我</li>
<li>评论</li>
</ul>
</li>
<li>微博
<ul class="inner">
<li>点赞</li>
<li>@我</li>
<li>评论</li>
</ul>
</li>
<li>微博
<ul class="inner">
<li>点赞</li>
<li>@我</li>
<li>评论</li>
</ul>
</li>
<li>微博
<ul class="inner">
<li>点赞</li>
<li>@我</li>
<li>评论</li>
</ul>
</li>
</ul>
<script>
var outer = document.querySelector('.outer');
var lis = outer.children;
for (var i = 0; i < lis.length; i++) {
lis[i].onclick = function () {
this.children[1].style.display = 'block';
}
lis[i].onmouseover = function () {
this.children[i].style.display = 'block';
}
}
</script>
3.兄弟节点
3.1返回当前元素的下一个兄弟节点,找不到则返回null,包含所有节点
node.nextSibling
3.2 返回当前元素的上一个兄弟节点,找不到则返回null,包含所有节点
node.previousSibling
3.3 返回当前元素的下一个兄弟元素节点,找不到则返回null(IE9以上支持)
node.nextElementSibling
3.4 返回当前元素的上一个兄弟元素节点,找不到则返回null,(IE9以上支持)
node.previousElementSibling
<body>
<div>我是div</div>
<span>我是span</span>
<script>
var div = document.querySelector('div');
var span = document.querySelector('span');
console.log(div.nextSibling)//#text
console.log(div.previousSibling);//#text
console.log(div.nextElementSibling);//<span>我是span</span>
console.log(div.previousElementSibling);//null
console.log(span.previousElementSibling);//<div>我是div</div>
</script>
</body>
4.创建和删除节点
4.1 创建节点,原来的页面中没有,根据需求动态产生
document.creatElement('tagName')
4.2 添加节点,节点创建好之后,需要添加才能显示,以下方法将一个节点添加至指定父节点的子节点列表末尾
node.appendChild(child)
4.3 在指定元素之前添加
node.insertBefore(child,指定元素)
<body>
<ul>
<li>123</li>
</ul>
<script>
//创建节点
var li = document.createElement('li');
var ul = document.querySelector('ul');
var lili = document.createElement('li');
//添加节点,在末尾添加
ul.appendChild(li);
ul.insertBefore(lili, ul.children[0]);
</script>
</body>
留言板案例
<body>
<textarea name="" id="" cols="30" rows="10"></textarea>
<button>发送</button>
<ul></ul>
<script>
//1/获取元素
var text = document.querySelector('textarea');
var btn = document.querySelector('button');
var ul = document.querySelector('ul');
//2.绑定和注册事件
btn.onclick = function () {
if (text.value === '') {
alert('请输入内容')
} else {
//创建li节点
var li = document.createElement('li');
//为li赋值
li.innerHTML = text.value;
//添加元素
// ul.appendChild(li); 在后面添加
ul.insertBefore(li, ul.children[0]);
}
}
</script>
</body>
5.删除节点
5.1 从DOM中删除一个子节点,返回删除的节点
node.removeChild(child)
<body>
<button>删除</button>
<ul>
<li>第一个</li>
<li>第二个</li>
<li>第三个</li>
<li>第四个</li>
</ul>
<script>
var ul = document.querySelector('ul');
var btn = document.querySelector('button');
btn.onclick = function () {
if (ul.children.length == 0) {
this.disabled = true;
} else {
ul.removeChild(ul.children[0]);
}
}
</script>
</body>
删除留言案例
<body>
<textarea name="" id="" cols="30" rows="10"></textarea>
<button>发送</button>
<ul></ul>
<script>
//1.获取元素
var text = document.querySelector('textarea');
var btn = document.querySelector('button');
var ul = document.querySelector('ul');
//2.注册事件
btn.onclick = function () {
if (text.value === '') {
alert('请输入内容');
} else {
var li = document.createElement('li');
li.innerHTML = text.value + "<a href='javascript:;'>删除</a>";//可以阻止链接的跳转
ul.insertBefore(li, ul.children[0]);
//删除当前li的父亲
var as = document.querySelectorAll('a');
//为所有的a添加点击事件
for (var i = 0; i < as.length; i++) {
as[i].onclick = function () {
//node.removeChild(child);删除的是li,当前a所在的li是this.parentNode
ul.removeChild(this.parentNode);
}
}
}
}
</script>
</body>
6.复制节点
node.cloneNode()
注意:如果括号内的参数为空或者false,则是浅拷贝,至克隆复制节点本身,不克隆里面的子节点
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
<script>
var ul = document.querySelector('ul');
var lili = ul.children[0].cloneNode();
var lilili = ul.children[0].cloneNode(true);
ul.appendChild(lili);
ul.appendChild(lilili);
</script>
</body>
表格动态生成案例
<style>
table {
border-collapse: collapse;
width: 100%;
}
thead {
border: 1px solid black;
background-color: skyblue;
height: 40px;
font-weight: bold;
}
td {
border: 1px solid grey;
text-align: center;
}
tbody {
background-color: pink;
}
</style>
<body>
<table>
<thead>
<td>姓名</td>
<td>科目</td>
<td>成绩</td>
<td>操作</td>
</thead>
<tbody>
</tbody>
</table>
<script>
//1/准备学生数据
var datas = [{
name: '小名',
subject: "Java",
score: 889,
}, {
name: '小名',
subject: "JavaScript",
score: 200,
}, {
name: '小名',
subject: "C++",
score: 12,
},
{
name: '小名',
subject: "C++",
score: 12,
}
];
//所有数据放在tbody中,先生成行,有几个人生成几行
var tbody = document.querySelector('tbody');
for (var i = 0; i < datas.length; i++) {
//创建行
var tr = document.createElement('tr');
// console.log(tr)
//添加行
tbody.appendChild(tr);
//行内创建单元格,单元格的数量取决于每个对象里面属性的个数
for (var k in datas[i]) {
//创建单元格
var td = document.createElement('td');
//添加到行中,同时把属性值给td
tr.appendChild(td);
td.innerHTML = datas[i][k];
}
//创建有删除的单元格
var td = document.createElement('td');
tr.appendChild(td);
//添加内容
td.innerHTML = "<a href='JavaScript:;'>删除</a>"
}
//删除操作
var as = document.querySelectorAll('a');
for (var i = 0; i < as.length; i++) {
as[i].onclick = function () {
//删除当前行
tbody.removeChild(this.parentNode.parentNode);
}
}
</script>
</body>
7.动态创建元素的三种方式
document.write()
文档流执行完毕,会导致页面重绘制,丢失由原来的元素,只剩创建的元素
<body>
<button>点击</button>
<p>abc</p>
<script>
//document.write() 文档流执行完毕,会导致页面重绘制,丢失由原来的元素,只剩创建的元素怒
var btn = document.querySelector('button');
btn.onclick = function () {
document.write(' <div>添加的元素</div>')
}
</script>
</body>
element.innerHTML
document.createElement()
<body>
<div class="inner"></div>
<div class="create"></div>
<script>
var inner = document.querySelector('.inner');
inner.HTML = '<a href="#">八八八</a>';
var create = document.querySelector('.create');
var a = document.createElement('a');
create.appendChild(a);
</script>
</body>
innerHTML将内容写入某个DOM节点,不会导致页面重绘
innerHTML创建多个元素效率更高(不要拼接字符串,采用数组形式拼接),结构稍微复杂些
createElement()创建多个元素效率稍微低一些,但是结构更清晰