<!-- 节点操作 -->
<!-- 为什么学习节点操作?之前利用DOM提供的方法过于繁琐且逻辑性不强 我们可以利用节点层级关系获取元素,利用父子兄弟关系获取元素 逻辑性强但兼容性稍差 节点操作更简单
节点:页面中所有内容都是节点(标签、文本、文档、注释等),在DOM中,节点使用node表示
HTML DOM树中的所有节点均可通过Javascript进行访问,所有HTML元素(节点)均可修改,也可以创建或删除
一般地,节点至少拥有三个基本属性:nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)
元素节点 nodeType 为1 属性节点 nodeType 为2 文本节点 nodeType 为3 (注意!文本节点包含文字、空格、换行等)
实际开发中主要操作元素节点-->
<!-- <div>
我是div
</div>
<span>我是span</span>
<ul>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
</ul>
<ol>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
</ol>
<div class="demo">
<div class="box"><span class="QRcode">X</span>
</div>
</div>
<script>
//1.父节点 parentNode
var QRcode=document.querySelector('.QRcode');
// var box=document.querySelector('.box'); 这是以前的写法,较为复杂
QRcode.parentNode; //获得QR的父节点
console.log(QRcode.parentNode); //获得的是box (得到的元素是最近的父级节点(亲爸爸),如果找不到父节点就返回 null)
//2.字节点 childNodes(标准的) 所有的子节点 包含元素节点、文本节点
var ul=document.querySelector('ul');
// console.log(ul.childNodes); //NodeList(11) [text, li, text, li, text, li, text, li, text, li, text] 将文本节点一起获取了
//从以上来看,我们一般不用 childNodes 来获取元素节点,一般要经过处理后才能获得元素节点
/* for(var i=0;i<ul.childNodes.length;i++){
if(ul.childNodes[i].nodeType == 1){
console.log(ul.childNodes[i]); //这样得到的就只有li元素了 但这样比较麻烦
}
} */
//可以用 children 获取所有子节点中的元素节点
console.log(ul.children); //也是实际开发常用
//第一个子节点 firstChild 不管是文本节点还是元素节点
console.log(ul.firstChild); //#text
//最后一个子节点 lastChild
console.log(ul.lastChild); //#text
//为了只获得元素节点,有另外的方法 firstElementChild lastElementChild 找不到就返回null 这两个方法有兼容性问题 ie9以上才支持
console.log(ul.firstElementChild); //li
console.log(ul.lastElementChild); //li
//解决方案(实际开发的写法 既没有兼容性问题又可以返回元素节点) children[](伪数组)
var ol=document.querySelector('ol');
console.log(ol.children[0]); //li
console.log(ol.children[4]); //li
console.log(ol.children[ol.children.length-1]); //有时候子元素太多,最后一个元素不好确定位置,可以利用子元素的长度减去1
//兄弟节点 nextSibling 得到下一个兄弟节点,包含元素节点和文本节点
var div=document.querySelector('div');
console.log(div.nextSibling); //#text
//上一个兄弟节点 previousSibling
console.log(div.previousSibling); //#text
//nextElementSibling 下一个兄弟元素节点
console.log(div.nextElementSibling);
//previousElementSibling 上一个兄弟元素节点
//但这两个还是有兼容性问题 ie9以上才支持 目前可以通过封装兼容性函数解决
function getNextElementSibling(element){
var el = element;
while(el==el.nextSibling){
if(el.nodeType==1){
return el;
}
return null;
}
}
</script>
-->
<!--创建节点:document.createElement('tagName') 因为原先这些元素不存在,所以也叫动态创建节点
添加节点:node.appendChild(child) 将一个节点添加到指定父节点的字节的列表末尾 -->
<!-- <ul>
<li>123</li>
</ul>
<script>
//创建元素节点 document.createElement('tagName')
var li=document.createElement('li');
//添加节点 node.appendChild(child) 将一个节点添加到指定父节点的字节的列表末尾
var ul=document.querySelector('ul');
ul.appendChild(li); //ul是父节点,li是子节点,被添加到了ul子节点的末尾 后面追加元素 类似于数组的push
//在父元素里指定子元素前面添加节点 node.inserBefore(child,指定元素)
var lili=document.createElement('li');
ul.insertBefore(lili,ul.children[0]);
</script> -->
<!-- 删除节点 node.removeChild(child) node父节点 child子节点-->
<!-- <button>删除</button>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var btn=document.querySelector('button');
var ul=document.querySelector('ul');
btn.οnclick= function(){
if(ul.children.length==0){
this.disabled=true;
}else{
ul.removeChild(ul.children[0]);
}
}
</script> -->
<!-- 复制节点(克隆节点) node.cloneNode-->
<!-- <ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var ul=document.querySelector('ul');
var lili=ul.children[0].cloneNode(); //node.cloneNode();括号里为空或者里面是false 浅拷贝 只复制标签,不复制里面的内容 /node.cloneNode(true);括号里为true 深拷贝 既复制标签也复制里面的内容
ul.appendChild(lili);
var lilili=ul.children[0].cloneNode(true);
ul.appendChild(lilili); //<li>1</li>
</script> -->
<!-- 三种动态创建元素的区别 -->
<!-- <button>点击</button>
<p>abc</p>
<div class="inner"></div>
<div class="create"></div>
<script>
//1.document.write() 创建元素 但是如果页面文档流加载完毕之后,再调用这个的话,会导致页面重绘(相当于重新加载了一个页面,页面中只有这句话里面的内容)
/* document.write('<div>124</div>'); //这样是可以的
var btn=document.querySelector('button');
btn.onclick = function(){
document.write('<div>345</div>'); //页面只剩345,其他东西都没有了
} */
//2.innetHTML 创建元素
var inner = document.querySelector('.inner');
inner.innerHTML='<a herf="#">百度</a>';
//3.createElment 创建元素
var create = document.querySelector('.create');
var a = document.createElement('a');
create.appendChild(a);
//!!面试常考:⭐
//innerHTML 创建多个元素效率更高(不要拼接字符串,采取数组方式拼接),结构稍微复杂一些
//createElement 创建多个元素效率稍低一些,但是结构更清晰
</script> -->
下拉菜单案例:
<style>
*{
padding: 0;
margin: 0;
}
.dv{
width: 500px;
}
li{
list-style: none;
}
.nav{
width: 500px;
margin: 100px ;
}
.nav>li{
width: 100px;
height: 50px;
background-color: rgb(251, 247, 242);
text-align: center;
float: left;
position: relative;
}
.nav li a{
display: block; /* 注意此处要转化为块级才能设置宽高 */
line-height: 50px;
width: 100px;
height: 50px;
color: rgb(57, 55, 55);
}
.nav>li>a:hover{
background-color: rgb(247, 221, 186);
color: #fb7426;
}
a{
text-decoration: none;
font-size: 16px;
}
.nav ul{
display: none;
position: absolute;
top: 50px;
border-left: 1px solid #fecc5b;
border-right: 1px solid #fecc5b;
}
.nav ul li{
width: 100px;
border-bottom: 1px solid #fecc5b;
}
.nav ul li:hover{
background-color: rgb(247, 221, 186);
}
.nav ul li a:hover{
color: #fb7426;
}
</style>
</head>
<body>
<div class="dv">
<ul class="nav">
<li ><a href="">登录</a>
<ul >
<li><a href="">注册</a></li>
<li><a href="">查看</a></li>
<li><a href="">···</a></li>
</ul>
</li>
<li ><a href="">微博</a>
<ul >
<li><a href="">私信</a></li>
<li><a href="">评论</a></li>
<li><a href="">@我</a></li>
</ul>
</li>
<li ><a href="">博客</a>
<ul >
<li><a href="">注册</a</li>
<li><a href="">查看</a</li>
<li><a href="">···</a></li>
</ul>
</li>
<li ><a href="">邮箱</a>
<ul >
<li><a href="">注册</a</li>
<li><a href="">查看</a</li>
<li><a href="">···</a></li>
</ul>
</li>
</ul>
</div>
<script>
var nav=document.querySelector('.nav');
var lis=nav.children; //获取子元素4个小li
for(var i=0;i<lis.length;i++){ //循环注册事件
lis[i].οnmοuseοver=function(){ //给每个子元素赋予鼠标经过事件
this.children[1].style.display='block'; //当前的li的第二个孩子的属性改变
}
lis[i].οnmοuseοut=function(){ //给每个子元素赋予鼠标离开事件
this.children[1].style.display='none';
}
}
</script>
简单版发布留言案例:
<style>
*{
padding: 0;
margin: 0;
}
div{
width: 500px;
margin: 100px auto;
}
p{
width: 495px;
height: 50px;
font-size: 20px;
padding-left: 5px;
line-height: 50px;
color: rgb(255, 255, 255);
background-color: rgb(250, 76, 76);
}
textarea{
margin-top: 2px;
margin-left: 2px;
padding-top: 5px;
font-size: 18px;
position: relative;
}
button{
width: 60px;
height: 40px;
background-color: rgb(249, 53, 53);
position: absolute;
top: 325px;
right:100px;
border: 1px solid rgb(135, 16, 16);
}
h2{
margin: 2px;
}
ul li{
height: 50px;
line-height: 50px;
list-style-type: none;
padding-left: 2px;
margin: 2px;
background-color: rgba(249, 3, 3, 0.096);
}
li a{
float: right;
text-decoration: none;
color: black;
}
a:hover{
color: red;
}
</style>
</head>
<body>
<!-- 核心思路:1.点击按钮,动态创建一个li,添加到ul里 2.创建li的同时,把文本域里面的值通过li.innerHTML赋值给li
3.如果想要把新的留言放到后面显示就用 appendChild 如果想要放到前面显示就用 inserBefore-->
<div>
<p>留言</p>
<textarea name="" id="" cols="40" rows="10"></textarea>
<button>发布</button>
<h2>留言板</h2>
<ul>
</ul>
</div>
<script>
var btn=document.querySelector('button');
var text=document.querySelector('textarea');
var ul=document.querySelector('ul');
btn.onclick = function(){
if(text.value==''){
alert('你没有输入内容');
}else{
var li = document.createElement('li');
li.innerHTML=text.value +'<a href="javascript:;">删除</a>' ; // javascript:;组织链接跳转 //把文本域的值赋给li的同时增加一个删除链接
ul.insertBefore(li,ul.children[0]);
//删除当前链接的父亲
var as= document.querySelectorAll('a'); //获取所有a元素
for(var i=0;i<as.length;i++){ //循环绑定事件
as[i].onclick = function(){ //给所有a元素绑定点击事件
ul.removeChild(this.parentNode); //当前元素为as,我们要删除它的父节点也就是li,而li的父节点又是ul,所以此处是ui.removeChild(this.parentNode)
}
}
}
}
</script>
动态生成表格案例:
<style>
*{
padding: 0;
margin: 0;
}
table{
border-collapse: collapse; /* 合并边框 */
width: 500px;
margin: 100px auto;
}
thead tr{
height: 40px;
background-color: rgb(199, 196, 196);
}
th,td{
border: 1px solid red;
text-align: center;
}
</style>
</head>
<body>
<!-- 动态生成表格案例:
分析:1.因为学生数据是动态的,我们需要Js动态生成。这里采用模拟数据自己去定义。数据采用对向形式存储
2.所有的数据放到tbody的行里面
3.因为行很多,通过循环创建多个行(根据人数决定多少行)
4.每个行里有多个单元格(对应的数据) 还要利用循环创建单元格并且把数据存放进去,也就是双重循环
5.最后一列单元格存放是是删除,需要单独创建单元格-->
<table>
<thead>
<tr>
<th>名字</th>
<th>科目</th>
<th>分数</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script>
//1.先准备好学生数据
var datas=[ //利用数组里存放对象来做
{
name:'卫英络',
subject:'JAvaScript',
score:'100'
},
{
name:'弘历',
subject:'JAvaScript',
score:'99'
},
{
name:'傅亨',
subject:'JAvaScript',
score:'98'
},
{
name:'明玉',
subject:'JAvaScript',
score:'88'
}
];
//2.往tbody里面创建行 有几个人就创建几行,根据数组长度
var tbody=document.querySelector('tbody');
for (var i=0 ;i<datas.length;i++){ //循环创建 外层管理行
var tr=document.createElement('tr');
tbody.appendChild(tr); //添加行
//创建列(单元格) 单元格要在行里创建 单元格的数量取决于对象的属性个数 要获得属性个数需要遍历对象
for(var k in datas[i]){ //遍历第i个对象(当外层循环到第i行时,第i1行放的就是第i个对象,则当前行的单元格就取决于当前行所对应的那个对象的属性个数,所以在第i个数组元素里遍历)
var td=document.createElement('td');
//把属性值给单元格 datas[i][k]得到的就是属性值 daras[i]就是对象
td.innerHTML=datas[i][k];
tr.appendChild(td);
}
//3.创建有删除的单元格
var td=document.createElement('td');
td.innerHTML='<a href="javascript:;">删除</a>';
tr.appendChild(td);
}
//4.删除操作
var as=document.querySelectorAll('a');
for(var i=0;i<as.length;i++){
as[i].onclick = function(){
//点击a删除当前所在行(a爸爸的爸爸) node.removr=eChild(child)
tbody.removeChild(this.parentNode.parentNode);
}
}
</script>