<>一、节点之间的层级:父子兄

节点主要 有父子兄关系

<>1.父节点操作

语法:子节点.parentNode,得到的是一个元素不是集合
比如我选了一个类名叫zzy的元素
var zzy = document.querySelector('.zzy');
那么要获取zzy 的父节点,只需要zzy.parentNode
console.log(zzy.parentNode);
注意,得到的时离该元素最近的父节点(亲爹),如果找不到父节点,就返回null

<>2.子节点操作

<>(1)父节点.childNodes(目测用的不多)

这个得到的是所有的子节点,除了我们想要的元素节点,还有换行、空格等文本节点,所以要想拿到元素,就要循环遍历,因为元素节点nodeType是1,属性2,文本3。这个真的是麻烦的一塌糊涂

<>(2)父节点.children(这个才是常用的)

这个只返回子元素节点,其他的都滚蛋,不错

<>3.获取第一个子元素和最后一个子元素

父节点.firstChild和父节点,lastChild,和父节点.childNodes差不多,返回的是所有类型节点中的第一个和最后一个,所以这两个用的不多,真正带劲的是:
父节点.firstElementChild和父节点.lastElementChild,这俩都是返回的第一个和最后一个元素节点,不错
但是!这个不错的方法,只有IE9以上支持。

<>这可咋办!

不要怕,在实际开发中,我们都会用父元素.children[i],既没有兼容问题,又能返回首尾元素节点
比如这里有这么几个东西
<ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> </ul>
那么首尾元素分别是:
var ul = document.querySelector('ul'); console.log(ul.children[0]); console.log
(ul.children[ul.children.length - 1]);
<>案例:下拉菜单

下拉菜单的常用布局:头部放个ul,ul里有几个li,每个li里面上边a,下边放ul包几个li
先放html和css
* { margin: 0; padding: 0; box-sizing: border-box; } li { list-style: none; } a
{ color: black; text-decoration: none; } .box { margin: 100px auto; width: 400px
; height: 50px; } .box>li { float: left; /* position: relative; */ width: 100px;
height: 50px; line-height: 50px; text-align: center; } .box>li a { display:
inline-block; width: 100px; height: 50px; } .box>li a:hover { background-color:
#ccc; } .box ul { display: none; /* position: absolute; */ left: 0; top: 50px;
border-left: 1px solid red; border-right: 1px solid red; } .box ul li {
border-bottom: 1px solid red; } .box li ul li:hover { background-color: rgb(247,
149, 149); } <ul class="box"> <li> <a href="#">微博</a> <ul> <li>私信</li> <li>评论</
li> <li>@我</li> </ul> </li> <li> <a href="#">微博</a> <ul> <li>私信</li> <li>评论</li>
<li>@我</li> </ul> </li> <li> <a href="#">微博</a> <ul> <li>私信</li> <li>评论</li> <li
>@我</li> </ul> </li> <li> <a href="#">微博</a> <ul> <li>私信</li> <li>评论</li> <li>@我
</li> </ul> </li> </ul>
然后是JavaScript,其实这部分代码比较好理解,就是我第一步获取元素老写错
var box = document.querySelector('.box'); //这个地方老写错…… var lis = box.children;
//得到4个li for (var i = 0; i < lis.length; i++) { lis[i].onmouseover = function ()
{ //鼠标放上去,这个li的第二个孩子(ul)显示 this.children[1].style.display = 'block'; } lis[i].
onmouseout = function () { this.children[1].style.display = 'none'; } }
<>4.获取兄弟节点

和父子一样,有个获取下一个(全部中的下一个)节点和上一个节点的方法,没什么p用

真正有用的是下面这个,但是又有兼容性问题

那咋办呢?实际上兄弟节点用的少,了解下就行了

<>二、节点的增删

<>1.创建和添加元素节点

先创建,再添加
比如我要创建一个li的元素节点
var myli = document.createElement('li');
<>(1)父元素.appendChild(要添加的元素)

先获取它的父元素,然后把我创建的li添加进去,默认是添加到父元素的尾部
var ul = document.querySelector('ul'); //把我创建的li放到ul里面去,默认添加到尾部 ul.appendChild(
myli);
<>(2)父元素.insertBefore(要添加的元素节点,添加到谁前面)

下面这个代码就是在ul的第一个孩子前添加我创建的li
ul.insertBefore(myli, ul.children[0]);
<>(3)简单添加留言案例
<textarea name="" id="content" cols="30" rows="10"></textarea> <button>发布</
button> <ul class="my"> <li></li> </ul>
注意获取textarea和input里面的值是.value
//简单留言案例 var content = document.querySelector('textarea');//获取文本域 var my =
document.querySelector('.my'); //获取ul var btn = document.querySelector('button')
; //获取button //点击按钮就生成一个li,添加到ul里 btn.onclick = function () { if (content.value
== '') { alert('您没有输入任何内容'); } else { var li = document.createElement('li'); li.
innerHTML= content.value; // my.appendChild(li); my.insertBefore(li, my.children
[0]); } }
<>2.删除元素节点

<>(1)使用父元素.removeChild(子元素)
<button>删除</button> <ul> <li>zzy</li> <li>aoaoao</li> <li>3213</li> </ul> var
ul= document.querySelector('ul'); var btn = document.querySelector('button');
btn.onclick = function () { if (ul.children.length != 0) { ul.removeChild(ul.
children[0]); } else { //如果删完了就禁用按钮 this.disabled = true; } }
<>(2)添加留言和删除留言(上面案例的升级版)

这里遇到个问题就是删除留言的代码要放到btn.onclick里面,要不然会先执行下面这段(注意代码的执行顺序),等点击btn的时候才添加a标签,那样先获取的as就是空了
//简单添加删除留言案例 var content = document.querySelector('textarea');//获取文本域 var my =
document.querySelector('.my'); //获取ul var btn = document.querySelector('button')
; //获取button //1.添加留言:点击按钮就生成一个li,添加到ul里 btn.onclick = function () { if (content
.value == '') { alert('您没有输入任何内容'); } else { var li = document.createElement(
'li'); //把textarea里面的内容取过来,然后再添加一个a标签 li.innerHTML = content.value + "<a
href='javascript:;'>删除</a>";//卧槽,还能这么写 // my.appendChild(li); my.insertBefore(li
, my.children[0]); } //2.删除留言 //先获取a标签
//这段代码要放到btn.onclick里面,要不然会先执行下面这段,等点击btn的时候才添加a标签,那样as就是空了 var as = document.
querySelectorAll('a'); for (var i = 0; i < as.length; i++) { as[i].onclick =
function () { my.removeChild(this.parentNode); } } }
<>3.复制元素节点

<>(1)语法:node.cloneNode()
<ul> <li>1</li> <li>2</li> <li>3</li> </ul>
把ul里的第一个孩子复制过来,放到ul的尾部
var ul = document.querySelector('ul'); var li1 = ul.children[0].cloneNode(); ul
.appendChild(li1);
<>(2)浅拷贝和深拷贝

node.cloneNode()括号里默认是false,也就是浅拷贝,只copy元素不copy内容
node.cloneNode(true),如果括号里是true就是深拷贝,copy元素和内容

<>三、动态生成表格

<>创建html和css
table { width: 400px; margin: 100px auto; text-align: center; border-collapse:
collapse; } th, td { border: 1px solid #333; } thead tr { height: 40px;
background-color: #ccc; } tbody tr { height: 30px; } <table cellspacing="0"> <
thead> <tr> <th>姓名</th> <th>科目</th> <th>成绩</th> <th>操作</th> </tr> </thead> <
tbody> </tbody>
<>1.先准备好学生的数据,以对象形式存储在数组中
var datas = [ { names: '彭于晏', subject: 'javascript', score: 87 }, { names: '小婷'
, subject: 'javascript', score: 100 }, { names: '张大仙', subject: 'javascript',
score: 99 }, { names: '刘亦菲', subject: 'javascript', score: 60 } ]
<>2.创建行tr
var tbody = document.querySelector('tbody'); for (var i = 0; i < datas.length;
i++) { //先创建,再添加,二者要绑定在一起 var tr = document.createElement('tr'); tbody.
appendChild(tr); }
<>3.创建行里面的单元格td
var tbody = document.querySelector('tbody'); for (var i = 0; i < datas.length;
i++) { //先创建,再添加,二者要绑定在一起 var tr = document.createElement('tr'); tbody.
appendChild(tr); //3.行里面创建单元格td for (var k in datas[i]) {
//遍历对象,k是属性的个数,有几个属性就循环几次 var td = document.createElement('td'); tr.appendChild(
td); }
<>4.添加td里面的数据

每个单元格的数据可以用对象里的datas[i][k]来获取
我的写法:

我一开始想获取所有的td元素数组,然后设置一个flag来获取相应的td,但是我发现这样的话因为每次循环td个数都在增加,所以td的数组也在变化,所以intd[flag]并不能添加每一行的数据,每次添加都是添加到第一行,除非flag=3*i。后来想了个办法,可以使用tr.children[flag],这样就可以实现给每行的每个单元格添加相应的数据
var tbody = document.querySelector('tbody'); for (var i = 0; i < datas.length;
i++) { //先创建,再添加,二者要绑定在一起 var tr = document.createElement('tr'); tbody.
appendChild(tr); //3.行里面创建单元格td var flag = 0; for (var k in datas[i]) {
//遍历对象,k是属性的个数,有几个属性就循环几次 var td = document.createElement('td'); tr.appendChild(
td); // var intd = document.getElementsByTagName('td'); //这是获取所有的td,包括前几行,不对 //
intd[flag].innerHTML = datas[i][k]; tr.children[flag].innerHTML = datas[i][k];
flag++; } }
看了老师的写法,我才知道我想多了……
其实只需要每次添加完td后,直接往td塞数据,然后再添加到tr里就行
var tbody = document.querySelector('tbody'); for (var i = 0; i < datas.length;
i++) { //先创建,再添加,二者要绑定在一起 var tr = document.createElement('tr'); tbody.
appendChild(tr); //3.行里面创建单元格td for (var k in datas[i]) {
//遍历对象,k是属性的个数,有几个属性就循环几次 var td = document.createElement('td'); //给每个单元格塞数据 td.
innerHTML= datas[i][k]; tr.appendChild(td); } }
<>5.添加删除操作的链接
var tbody = document.querySelector('tbody'); for (var i = 0; i < datas.length;
i++) { //先创建,再添加,二者要绑定在一起 var tr = document.createElement('tr'); tbody.
appendChild(tr); //3.行里面创建单元格td for (var k in datas[i]) {
//遍历对象,k是属性的个数,有几个属性就循环几次 var td = document.createElement('td');
//4.给每个单元格先塞数据,再放到tr里 td.innerHTML = datas[i][k]; tr.appendChild(td); }
//5.添加删除操作的链接 var tdend = document.createElement('td'); tdend.innerHTML = "<a
href='javascript:;'>删除</a>"; tr.appendChild(tdend); }
<>6.最后一步,给删除操作添加删除事件
//2.先创建行tr,有几个人就创建几行 var tbody = document.querySelector('tbody'); for (var i =
0; i < datas.length; i++) { //先创建,再添加,二者要绑定在一起 var tr = document.createElement(
'tr'); tbody.appendChild(tr); //3.行里面创建单元格td for (var k in datas[i]) {
//遍历对象,k是属性的个数,有几个属性就循环几次 var td = document.createElement('td');
//4.给每个单元格先塞数据,再放到tr里 td.innerHTML = datas[i][k]; tr.appendChild(td); }
//5.添加删除操作的链接 var tdend = document.createElement('td'); tdend.innerHTML = "<a
href='javascript:;'>删除</a>"; tr.appendChild(tdend); } //6.给删除按钮添加事件 var as =
document.querySelectorAll('a'); //这里一定要是All for (var i = 0; i < as.length; i++)
{ as[i].onclick = function () { tbody.removeChild(this.parentNode.parentNode); }
}
<>四、innerHTML和createElement创建元素谁效率更高?

如果innerHTML是拼接字符串标签的话,拼1000个要用3000ms,但是如果采用数组形式拼接,只用7ms
如果用createElement创建1000个同样的元素,大概18ms

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信