jsのDOM页面交互
一、API与WebAPI
1.1.API解读
- API(应用程序编程接口):是预先定义的函数,为编程人员提供的调用功能,无须访问源码理解内部工作机制和细节
- WebAPI:是浏览器提供的一套操作浏览器功能和页面元素的API(BOM和DOM),为了与浏览器进行交互
二、DOM
- DOM:文档对象模型,是W3C提供的处理可扩展标记语言(HTML或XML)的编程接口,可以改变网页的内容、结构和样式
2.1.DOM树
DOM将以下内容都看做是对象(众生皆对象)
- 文档:一个页面就是一个文档,DOM中用document表示
- 元素:页面中所有标签都是元素,DOM中用element表示
- 节点:网页中所有内容都是节点(标签节点,属性节点,文本节点,注释节点等),DOM中用node表示
2.2.获取文档对象
- document.body:返回body元素
- document.documentElement:返回html元素
var mybody=document.body
var myhtml=document.documentElement
console.log(myhtml)
- document.getElementById(‘id’):根据 id 获取文档对象
返回整个文档对象- document.getElementById(‘标签名’):根据 标签名 获取文档对象
返回一个指定 标签名的 对象的集合,无论是空 是一条 还是多条,都以伪数组的形式存储- 父元素.getElementsByTagName(‘标签名’):获取父元素内部所有指定标签的子元素
注意:父元素必须是指定的单个对象(可以使用id来获取父元素),获取时不包含父元素自己
<div id="time">2019-12-21</div>
<div id="time2">2019-12-22</div>
<div id="time3">
<span>这是time3的span标签</span>
</div>
<div id="time4">
<span>这是time4的span标签</span>
</div>
<!-- 因为文档是从上往下加载的,所以得先有标签,再进行操作,所以把script写到标签下面 -->
<script>
var timer = document.getElementById('time')
console.log(timer) // 结果是 <div id="time">2019-12-21</div>
console.log(typeof timer) // 类型是 object 类型
console.dir(timer) // 结果 div#time , console.dir 可以打印出元素对象的属性和方法
var timers = document.getElementsByTagName('div')
console.log(timers) // HTMLCollection(2) [div#time, div#time2, time: div#time, time2: div#time2]
console.log(timers[0]) // 结果是 <div id="time">2019-12-21</div>
var time3=document.getElementById('time3')
var time3_span=time3.getElementsByTagName('span')
console.log(time3_span)
</script>
H5新增选择器,IE6,7,8不兼容
- document.getElementsByClassName(‘类名’):根据类名获取元素集合
- document.querySelector(’.box / #nav / li '):回指定选择器的 第一个 元素对象
注意选择器里面需要加符号 .box(类),#nav(id),li(标签)
- document.querySelectorAll(’.box / #nav / li '):返回指定选择器的 所有 元素对象
<div class="box">盒子1</div>
<div class="box">盒子2</div>
<div id="nav">
<ul>
<li>首页</li>
<li>产品</li>
</ul>
</div>
<script>
var boxs = document.getElementsByClassName('box')
var firstBox=document.querySelector('.box')
var firstNav=document.querySelector('#nav')
var firstLi=document.querySelector('li')
console.log(firstNav)
var AllBox=document.querySelectorAll('.box')
console.log(AllBox)
</script>
2.3.事件三要素
- 事件源:事件被触发的对象(如按钮)
- 事件类型:干什么(如鼠标点击onclick,鼠标经过,键盘按下等)
- 事件处理程序:怎么做,通过一个匿名函数赋值方式完成
- 触发事件后,里面使用的this指向事件的调用者
<button id="btn">唐伯虎</button>
<script>
// 事件源 btn
var btn=document.getElementById('btn')
// 事件类型 onclick
// 事件处理程序 function
btn.onclick = function() {
alert('点秋香')
}
// 也可以不触发事件源,直接在script进行事件的触发
alert("这里是不触发事件源的弹出")
</script>
鼠标常见事件 | 触发条件 |
---|---|
onclick | 鼠标点击左键触发 |
onmouseover | 鼠标经过触发 |
onmouseout | 鼠标离开触发 |
onfouse | 获得鼠标焦点触发 |
onblur | 失去鼠标焦点触发 |
onmousemove | 鼠标移动触发 |
onmouseup | 鼠标弹起触发 |
onmousedown | 鼠标按下触发 |
2.4.操作元素内容及属性
- js可以通过DOM操作网页的内容(增删改html标签内的内容和属性),结构(增删html标签),样式(css)
API | 解释 |
---|---|
对象.innerText=‘要写入对象的内容’ | 修改元素内容(保留html标签,会将标签直接打印出来,非标准) |
对象.innerHTML=‘要写入对象的内容’ | 修改元素内容(识别html标签,W3C标准) |
对象.innerText | 获取元素内容(不保留html标签,空格和换行) |
对象.innerHTML | 获取元素内容(保留html标签,空格和换行) |
img对象.src=‘新的路径’ | 修操作元素属性,改图片的src路径 |
img对象.title=‘新文字’ | 修操作元素属性,修改鼠标放到图片上显示的文字 |
// 1
<button id="btn">获取当前的系统时间</button>
<div id="div">某个时间</div>
// 2
<p>
我是文字
<span>123</span>
</p>
// 3
<img id="img" src="./img/lingerxiang.jpg" title="铃儿响">
<button id="lingerxiang">铃儿响</button>
<button id="xuezhiqian">丑八怪</button>
<script>
// 1
var btn=document.getElementById('btn')
var div=document.getElementById('div')
btn.onclick = function(){
div.innerText=getDate()
}
function getDate(){
var date=new Date()
var year=date.getFullYear()
var month=date.getMonth()+1
var dates=date.getDate()
var hours=date.getHours()
var minutes=date.getMinutes()
var seconds=date.getSeconds()
var day=date.getDay()
var days=['星期日','星期一','星期二','星期三','星期四','星期五','星期六']
return '今天是'+year+"年"+month+"月"+dates+"日,"+days[day]+","+hours+":"+minutes+":"+seconds
}
// 2
btn.onclick = function(){
div.innerText='<strong>今天是:</strong>2019年12月21日' // 不会将<strong>解释
div.innerHTML='<strong>今天是:</strong>2019年12月21日' // 会将<strong>解释
}
var p=document.querySelector('p')
console.log(p.innerText) // 会将html标签解释
console.log(p.innerHTML) // 会将html标签直接打印出来
// 3
var img=document.getElementById('img')
var lingerxiang=document.getElementById('lingerxiang')
var xuezhiqian=document.getElementById('xuezhiqian')
lingerxiang.onclick = function(){
img.src="./img/lingerxiang.jpg"
img.title="铃儿响"
}
xuezhiqian.onclick = function(){
img.src="./img/xuezhiqian.jpg"
img.title="薛之谦"
}
</script>
2.5.操作表单元素的属性
属性 | 解释 |
---|---|
type | 表单元素类型 |
value | 表单元素的内容 |
checked | 表单元素被选中 |
selected | 下拉列表被选中 |
disabled | 表单元素被禁用 |
<button id="btn">点击</button>
<input type="text" value="请输入内容"></input>
<script>
var btn=document.getElementById('btn')
var input=document.querySelector('input')
btn.onclick = function(){
input.value="你已经点击过按钮了" // 将输入框的内容进行修改
this.disabled=true // 并将按钮禁用,this指向事件的调用者btn
}
</script>
2.5.1.显示隐藏密码明文小案例
以后遇到一个按钮可以点击多次对应不同的操作,就可以设置一个flag变量来进行操作
<!-- 点击按钮将密码框切换为文本框 -->
请输入密码:<input type="password"></input>
<button id="btn">小眼睛</button>
<script>
var btn=document.getElementById('btn')
var input=document.querySelector('input')
var flag=0 // 当前是密码框时flag=0,当前是文本框是flag=1
btn.onclick = function(){
if(flag==0){
input.type="text" // 将输入框的type='password' 改为type='text'就变成明文的了
flag=1
}else{
input.type="password"
flag=0
}
}
</script>
2.6.操作元素样式属性(style)
修改元素的大小,颜色和位置等style样式
- 对象.style.样式:行内样式操作
里面的样式采用驼峰命名法,如backgroundColor
修改后采用的是行内样式(在浏览器中会将样式直接加到行内样式中去),css中行内样式权重高- 对象.className:类名样式操作
修改为另一个内嵌式样式,使用类来改变,用来修改样式和功能比较复杂的对象
注意:如果原来对象没有类名,会将这个类名加入该对象,如果原来的对象有类名,且不一样,会直接进行覆盖,如果不想覆盖元类名,可以使用多类名选择器:this.className="原类名 新类名"
// 行内样式操作
<style>
#div{
background-color: aqua;
width: 80px;
height: 80px;
}
</style>
<div id="div"></div>
<script>
var div=document.querySelector("#div")
div.onclick = function(){
this.style.backgroundColor="yellow"
this.style.width="150px"
}
</script>
// 类名样式操作
<style>
.div{
background-color: aqua;
width: 80px;
height: 80px;
}
.div2{
color: yellow;
}
</style>
<div class="div">这是里面的文字内容</div>
<script>
var div=document.querySelector(".div")
div.onclick = function(){
this.className="div2" // 将原来的class="div"覆盖为class="div2"
this.className="div div2" // 将原来的class="div"改为class="div div2" ,不会覆盖原类名
}
</script>
2.6.1.盒子的显示与隐藏案例
display:none
:隐藏盒子
display:block
:显示盒子
<div class="div"></div>
<button id="btn">点击</button>
<script>
var div=document.querySelector('.div')
var btn=document.getElementById('btn')
var flag=1 // 1表示显示,0表示隐藏
btn.onclick = function(){
if(flag==1){
div.style.display='none' // 要记得这个隐藏之后就不占空间了
flag=0
}else{
div.style.display='block'
flag=1
}
}
</script>
2.6.2.显示隐藏文本框中的内容案例
- onfocus:文本框获取焦点
- onblur:文本框失去焦点
<input type="text" value="手机" style="color: #999;"></input>
<script>
var text=document.querySelector("input")
text.onfocus = function(){ // 获取焦点时隐藏文字
if(this.value === '手机'){
this.value=""
}
this.style.color="#333"
}
text.onblur = function(){ // 失去焦点时复原文字
if(this.value === ''){
this.value="手机"
}
this.style.color="#999"
}
</script>
2.6.3.注册验证案例:判断密码是否在6-16位
<input type="text"></input>
<span style="color: #999;font-size: 14px;">请输入6-16位的密码</span>
<script>
var text=document.querySelector('input')
var span=document.querySelector('span')
text.onblur = function(){
var len=this.value.length
if(len>=6 && len<=16){
span.innerHTML='您输入的正确'
span.style.color="green"
}else{
span.innerHTML='错误,请输入6-16位的密码'
span.style.color="red"
}
}
</script>
2.7.小案例
2.7.1.按钮排他
如果由于同一组元素,想要某一个元素实现某种样式,需要用到循环的排他思想算法
- 先将其他所有元素的样式清除
- 给当前的元素设置样式
实现点击某个按钮背景颜色变化,其他背景颜色变回原来的颜色
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
var btns=document.getElementsByTagName('button')
for(var i=0;i<btns.length;i++){
btns[i].onclick = function(){
for(var i=0;i<btns.length;i++){
btns[i].style.backgroundColor=''
}
this.style.backgroundColor='green'
}
}
</script>
2.7.2.换页面皮肤效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>百度换肤案例</title>
<style>
*{
margin: 0;
padding: 0;
}
body{
background: url(./img/1.jpg) no-repeat center top;
}
li{
list-style: none;
}
.baidu{
overflow: hidden;
margin: 100px auto;
background-color: #fff;
width: 410px;
padding-top: 3px;
}
.baidu li{
float: left;
margin: 0 1px;
cursor: pointer;
}
.baidu img{
width: 100px;
}
</style>
</head>
<body>
<ul class="baidu">
<li><img src="./img/1.jpg"></li>
<li><img src="./img/2.jpg"></li>
<li><img src="./img/3.jpg"></li>
<li><img src="./img/4.jpg"></li>
</ul>
<script>
// 获取被点击的图片
var imgs=document.querySelector('.baidu').querySelectorAll('img')
for(var i=0;i<imgs.length;i++){
imgs[i].onclick = function(){
document.body.style.backgroundImage = 'url('+this.src+')'
}
}
</script>
</body>
</html>
2.7.3.隔行变色、全选和取消全选小案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>表格隔行变色案例</title>
<style>
table{
border: 1px solid #999;
font-size: 14px;
width: 400px;
text-align: center;
}
</style>
</head>
<body>
<table>
<thead>
<tr style="background-color: rgb(29, 162, 167);">
<td><input type="checkbox" id="checkdAll"></input></td>
<td>ID</td>
<td>姓名</td>
<td>年龄</td>
<td>性别</td>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" name="people"></input></td>
<td>1</td>
<td>小黄</td>
<td>18</td>
<td>男</td></td>
</tr>
<tr>
<td><input type="checkbox" name="people"></input></td>
<td>2</td>
<td>小白</td>
<td>20</td>
<td>女</td></td>
</tr>
<tr>
<td><input type="checkbox" name="people"></input></td>
<td>3</td>
<td>小黑</td>
<td>25</td>
<td>男</td></td>
</tr>
</tbody>
</table>
<script>
var trs=document.querySelector('tbody').querySelectorAll('tr')
for(var i=0;i<trs.length;i++){
trs[i].onmouseover = function(){
this.style.backgroundColor='rgb(29, 162, 167)'
}
trs[i].onmouseout = function(){
this.style.backgroundColor='white'
}
}
var checkboxAll=document.getElementById('checkdAll')
var checkboxs=document.querySelector('tbody').getElementsByTagName('input')
checkboxAll.onclick = function(){
// 获取checkboxAll当前的选定状态 ,如果被选定为true,不背选定为false
var flag=this.checked
if(flag){
for(var i=0;i<checkboxs.length;i++){
checkboxs[i].checked=true
}
}else{
for(var i=0;i<checkboxs.length;i++){
checkboxs[i].checked=false
}
}
}
// 如果下面的按钮有一个未被选中,就取消全选
for (var i=0;i<checkboxs.length;i++){
// 给每一个小按钮设置一个点击事件
checkboxs[i].onclick = function(){
var flag=true // false是没有被全选,true是被全选了
// 循环检查每一个小按钮是否被选中,如果有一个未被选中flag=0
for (var i=0;i<checkboxs.length;i++){
if(!checkboxs[i].checked){
flag=false
break // 退出for循环,只要有1个没有被选中就可以退出了
}
}
checkboxAll.checked=flag
}
}
</script>
</body>
</html>
2.8.操作自定义元素属性
- 为什么要使用H5自定义属性
为了保存并使用数据,有些数据可以只保存到页面,不用保存到数据库中- 怎么避免自定义属性和内置属性的歧义
H5规定自定义属性使用data-属性名
在html标签中定义属性:<div data-index="1"></div>
使用js设置属性:element.setAttribute('data-index',2)
2.8.1.获取自定义元素属性值
- element.属性名:只能获取内置属性值(元素本身自带的属性)
- element.getAttribute(‘属性名 / data-属性名’):除了内置属性,还可以获得自定义属性(推荐使用,兼容性好)
- H5新增(ie11才支持):element.dataset.属性名(不加data-):dataset是一个集合,里面存放了所有以data开头的自定义属性
- H5新增(ie11才支持):element.dataset[‘属性名’]:如果自定义属性有多个 - 链接的单词,获取时属性名采用驼峰命名法
<div id="demo" data-index="1" data-list-name="lili"></div>
<script>
var demo=document.getElementById('demo')
console.log(demo.id)
console.log(demo.getAttribute('id'))
console.log(demo.getAttribute('data-index')) // data-index为自定义属性
console.log(demo.dataset.index))
console.log(demo.dataset['index']))
console.log(demo.getAttribute('data-list-name'))
console.log(demo.dataset.listName))
console.log(demo.dataset['listName']))
</script>
2.8.2.修改自定义元素属性值
- element.属性=‘值’:只能设置内置属性值(元素本身自带的属性)
- element.setAttribute(‘属性’,‘值’):除了内置属性,还可以设置自定义属性(推荐使用)
<div id="demo" class="nav" index="1"></div>
<script>
var demo=document.getElementById('demo')
demo.className="navs" // 注意:原来的方法中属性名为className
console.log(demo.className)
demo.setAttribute('class','navs2') // 但使用set/getAttribute就是class
console.log(demo.getAttribute('class'))
</script>
2.8.3.删除自定义元素属性值
- element.removeAttribute(‘属性’):删除内置或自定义属性
demo.removeAttribute('index')
2.8.4.tab栏切换案例(重点)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.tab_list ul{
margin: 0;
padding: 0;
width: 540px;
height: 30px;
background-color: rgb(247, 243, 243);
border: 1px solid rgb(189, 183, 183);
border-bottom: 2px solid red;
}
.tab_list ul li{
list-style: none;
width: 20%;
height: 100%;
float: left;
text-align: center;
font-size: 13px;
vertical-align: auto;
line-height: 30px;
color: gray;
}
.tab_list ul li:nth-child(4){
width: 40%;
}
.tab_list .current{
background-color: red;
color: white;
}
.tab_content div img{
width: 530px;
height: 200px;
margin-top: 10px;
}
.item{
/* 先将所有的item隐藏起来 */
display: none;
}
.item:nth-child(1){
/* 再把第一个item显示出来 */
display: block;
}
</style>
</head>
<body>
<div class="tab">
<div class="tab_list">
<ul>
<li class="current">商品介绍</li>
<li>规格与包装</li>
<li>售后保障</li>
<li>商品评价(1.1万+)</li>
</ul>
</div>
<div class="tab_content">
<div class="item">
<img src="./img/6.jpg">
</div>
<div class="item">
<img src="./img/7.jpg">
</div>
<div class="item">
<img src="./img/8.jpg">
</div>
<div class="item">
<img src="./img/9.jpg">
</div>
</div>
</div>
<script>
var lis=document.querySelector('.tab_list').querySelectorAll('li')
var items=document.querySelectorAll('.item')
for(var i=0;i<lis.length;i++){
// 为什么到里面i=4,因为只是先给每个小li绑定一个onclick事件,由于没有点击,所以就没有进入函数,当点击时进入函数,i就已经等于4了
// 所以:核心算法,给5个小li分别设置索引号
lis[i].setAttribute('index',i)
lis[i].onclick = function(){
// 排他思想:将其他小li去掉背景和文字颜色
for(var j=0;j<lis.length;j++){
lis[j].removeAttribute('class')
}
this.setAttribute('class','current')
// 点击某一个小li获取设置的index
var index = this.getAttribute('index')
// 排他思想:将其他div隐藏,只有被点击的div显示
for(var j=0;j<items.length;j++){
items[j].style.display = 'none'
}
items[index].style.display = 'block'
}
}
</script>
</body>
</html>
2.9.节点操作
获取元素的两种方式
- 使用DOM提供的方法:getElementById、querySelector(逻辑性不强)
- 利用节点层级关系获取元素:利用父子兄节点关系获取元素(更简单,逻辑性强,但兼容性稍差)
节点的内容
- nodeType:节点类型
元素节点(主要操作对象) nodeType=1,属性节点 nodeType=2,文本节点 nodeType=3(文本节点包括文字,空格和换行等)- nodeName:节点名称
- nodeValue:节点值
节点可以分为 父 子 兄 的关系
2.9.1.父节点
- 子节点对象.parentNode:可以得到子节点对象的父节点对象,如果找不到父节点就返回为null
注意:得到的是离子节点最近的父节点(亲爸爸,爷爷找不到)
<div class="box">
<span class="erweima">×</span>
</div>
<script>
var erweima=document.querySelector('.erweima')
var box=erweima.parentNode
console.log(box)
</script>
2.9.2.子节点
格式 | 解释 |
---|---|
父节点对象.childNodes | 获取所有子节点(包含元素 和 文本(换行)等节点)(标准) |
父节点对象.children | 获取所有子元素节点(非标准)(但开发中一般只操作子元素,所以这个较上一个常用) |
父节点对象.firstChild | 获取第一个子节点(包括元素和文本等所有节点) |
父节点对象.lastChild | 获取最后一个子节点(同上) |
父节点对象.firstElementChild | 获取第一个元素节点(有兼容性问题,ie9以后才支持) |
父节点对象.lastElementChild | 获取最后一个元素节点(同上) |
父节点对象.children[0] | 获取第一个元素节点(实际开发中使用,即会返回第一个元素节点,又不会有兼容性问题) |
父节点对象.children[ul.children.length-1] | 获取最后一个元素节点(同上) |
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var ul=document.querySelector('ul')
console.log(ul.childNodes) // 包含所有子节点
console.log(ul.childNodes[0].nodeType) // 3 文本节点
console.log(ul.childNodes[1].nodeType) // 1 元素节点
console.log(ul.children) // 只包含元素节点
console.log(ul.firstChild) // 获取第一个子节点(包括元素和文本等所有节点)
console.log(ul.lastChild) // 获取最后一个子节点
console.log(ul.firstElementChild) //获取第一个元素节点(有兼容性问题,ie9以后才支持)
console.log(ul.lastElementChild) //获取最后一个元素节点
console.log(ul.children[0]) //获取第一个元素节点(实际开发中使用,即会返回第一个元素节点,又不会有兼容性问题)
console.log(ul.children[ul.children.length-1]) //获取最后一个元素节点
</script>
2.9.3.新浪下拉菜单案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>新浪下拉菜单</title>
<style>
*{
margin: 0;
padding: 0;
}
a{
text-decoration: none;
font-size: 14px;
}
li{
list-style: none;
}
.nav{
margin: 50px;
}
.nav>li{
position: relative;
float: left;
width: 80px;
height: 40px;
text-align: center;
}
.nav li a{
display: block;
width: 100%;
height: 100%;
line-height: 40px;
color: #333;
}
.nav>li>a:hover{
background-color: #eee;
}
.nav ul{
display: none;
position: absolute;
top: 41px;
left: 0;
width: 80px; /* ul的宽度 */
border-left: 1px solid #fecd5b9c;
border-right: 1px solid #fecc5B;
}
.nav ul li{
border-bottom: 1px solid #fecd5b9c;
}
.nav ul li a:hover{
background-color: #FFF5DA;
}
</style>
</head>
<body>
<!-- 导航栏里面放3个小li,每个小li里面用的是a超链接,和ul,再讲ul定位到a标签下面 -->
<ul class="nav">
<li>
<a href="#">登录</a>
</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>
</ul>
</li>
<li>
<a href="#">邮箱</a>
<ul>
<li><a href="#">免费邮箱</a></li>
<li><a href="#">VIP邮箱</a></li>
<li><a href="#">企业邮箱</a></li>
</ul>
</li>
</ul>
<script>
var nav=document.querySelector('.nav')
var lis=nav.children; // 得到3个小li
for(var i=0;i<lis.length;i++){
// 当鼠标移入时让当前小li的第二个孩子children[1],ul显示
lis[i].onmouseover = function(){
this.children[1].style.display= 'block'
}
// 鼠标移出时隐藏
lis[i].onmouseout = function(){
this.children[1].style.display= 'none'
}
}
</script>
</body>
</html>
2.9.4.兄弟节点
格式 | 解释 |
---|---|
兄弟节点对象.previousSibling | 得到上一个兄弟节点(包括文本和元素节点,找不到返回null) |
兄弟节点对象.nextSibling | 得到下一个兄弟节点(同上) |
兄弟节点对象.previousElementSibling | 得到上一个兄弟元素节点(只有元素节点,找不到返回null,有兼容性问题,到ie9以上才支持) |
兄弟节点对象.nextElementSibling | 得到下一个兄弟元素节点(同上) |
getnextElementSibling | 封装一个兼容性函数 |
<span>这是我的上一个兄弟节点span</span>
<div>我是div</div>
<span>这是我的下一个兄弟节点span</span>
<script>
var div=document.querySelector('div')
console.log(div.previousSibling) // 得到上一个兄弟节点(包括文本和元素节点,找不到返回null)
console.log(div.nextSibling) // 得到下一个兄弟节点(同上)
console.log(div.previousElementSibling) // 得到上一个兄弟元素节点(只有元素节点,找不到返回null,有兼容性问题,到ie9以上才支持)
console.log(div.nextElementSibling) // 得到下一个兄弟元素节点(同上)
// 解决兼容性问题(通过封装一个兼容性函数)
function getnextElementSibling(element){
var el=element
// nextSibling是将所有的节点都获取到,然后进行循环判断,如果nodeType=1代表其是元素节点,就将其作为元素节点返回,其他节点则返回为null
while(el=el.nextSibling){
if(el.nodeType === 1){
return el
}
}
return null
}
</script>
2.9.5.创建、添加、删除节点
由于原节点是不存在的,需要动态创建元素节点后才能进行添加
格式 | 解释 |
---|---|
document.createElement(‘tagName’) | 创建指定标签的html元素 |
父节点.appendChild(子元素节点) | 将子节点追加到指定父节点列表的末尾(类似于css里的after伪元素) |
父节点.insertBefore(子元素节点,指定元素节点) | 将子节点添加到父节点中指定元素节点之前 |
<ul>
<li>这是第一个小li</li>
</ul>
<script>
// 创建指定标签名的元素节点(创建的一个节点只能被添加1次,如果多次添加的话会以后一次添加的为准)
var li=document.createElement('li')
// 将子节点追加到父节点的末尾
// 获取父节点
var ul=document.querySelector('ul')
ul.appendChild(li)
// 将子节点追加到父节点中指定节点的前面
var lili=document.createElement('li')
ul.insertBefore(lili,ul.children[0]) // 将li添加到ul的第一个子节点的前面
</script>
动态创建元素的区别
document.write()
直接将内容写入页面的内容流,当文档执行完毕(window.onload),会导致页面全部重绘(原前的东西都会消失,只显示用write写入的内容)
document.createElement('a')
不会导致页面重绘,效率比innerHTML是数组形式要低
element.innerHTML=<a href="javascript:;">删除</a>
不会导致页面重绘,字符串拼接的效率低,数组追加的效率要高
可阻止超链接跳转:href="javascript:;" 或 href="javascript:void(0);"
效率:总之不同浏览器下,当创建多个元素时,innerHTML效率要高于createElement
innerHTML的数组拼接形式 > createElement > innerHTML的字符串拼接
<div class="inner"></div>
<script>
var inner=document.querySelector('.inner')
var arr=[]
for(var i=0;i<=100;i++){
arr.push('<a href="#">百度</a>')
}
inner.innerHTML = arr.join('') // 默认以逗号形式分隔数组
</script>
2.9.6.删除节点
格式 | 解释 |
---|---|
父节点.removeChild(子节点) | 删除一个子节点,返回被删除的节点 |
父节点.removeChild(父节点.children[0]) | 删除父节点的第一个子节点,返回被删除的节点 |
<ul>
<li>光头强</li>
<li>熊大</li>
<li>熊二</li>
</ul>
<button>点击按钮依次删除</button>
<script>
var btn=document.querySelector('button')
var ul=document.querySelector('ul')
btn.onclick = function(){
if(ul.children.length == 0){
alert('没有可删除的内容')
}else{
ul.removeChild(ul.children[0]) // 删除ul的第0个孩子
}
}
</script>
2.9.7.复制克隆节点
格式 | 解释 |
---|---|
被复制节点.cloneNode(false/不填) | 浅复制,只复制节点本身,不复制里面的子节点 |
被复制节点.cloneNode(true) | 深复制,复制节点本身和里面的子节点 |
<ul>
<li>这是一个li</li>
</ul>
<script>
var ul=document.querySelector('ul')
var li=ul.children[0]
var lightcopyli=li.cloneNode() // 参数为空或false,浅复制,只复制节点本身,不复制里面的子节点
var deepcopyli=li.cloneNode(true) // 参数为true,深复制,复制节点本身和里面的子节点
ul.appendChild(lightcopyli)
ul.appendChild(deepcopyli)
</script>
2.9.8.留言板发布删除小案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>留言板发布</title>
<style>
textarea{
width: 200px;
height: 100px;
}
button{
position: relative;
bottom: 7px;
}
li{
font-size: 14px;
background-color: plum;
width: 400px;
margin-top: 10px;
}
li a{
float: right; /* 设置 删除按钮 在最右边*/
color: gray;
text-decoration: none;
margin-right: 20px;
}
</style>
</head>
<body>
<textarea></textarea>
<button>发布</button>
<ul>
<li>123</li>
</ul>
<script>
// 当点击发布按钮时
var send=document.querySelector('button')
send.onclick = function(){
// 获取textarea中的内容
var textarea=document.querySelector('textarea')
if(textarea.value == ''){
alert('您没有输入内容')
}else{
// 创建一个li
var li=document.createElement('li')
// 将li的内容设置为在textarea中输入的内容
li.innerHTML = textarea.value + '<a href="javascript:;">删除</a>' // 阻止超链接跳转: href="javascript:;" 或 href="javascript:void(0);"
// 将创建的li追加到ul的末尾
var ul=document.querySelector('ul')
// ul.appendChild(li)
// 最后发布的留言在最前面显示
ul.insertBefore(li,ul.children[0])
// 将textarea中的内容清空
textarea.value=''
// 删除留言
// 将所有的删除留言超链接拿过来
var deletea=document.querySelectorAll('a')
for(var i=0;i<deletea.length;i++){
deletea[i].onclick = function(){
// 删除当前删除按钮所在发父节点li this.parentNode ,在父节点ul下进行删除
ul.removeChild(this.parentNode)
}
}
}
}
</script>
</body>
</html>
2.9.9.动态生成表格和删除行小案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>动态生成表格和删除行</title>
<style>
table {
width: 500px;
margin: 100px auto;
border-collapse: collapse; /*设置表格的边框被合并为一个单一的边框*/
text-align: center;
}
td,th{
border: 1px solid #333;
}
thead tr{
height: 40px;
background-color: #ccc;
}
td a{
text-decoration: none;
color: gray;
}
</style>
</head>
<body>
<table cellspacing="0" cellpadding="0" border="1">
<thead>
<tr>
<th>姓名</th>
<th>科目</th>
<th>成绩</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script>
// 创建学生对象数组(模拟数据,真正的数据是从数据库中获得的)
var students=[
{
name:'肖战',
subject:'软件工程',
score:100
},
{
name:'王耶啵',
subject:'人工智能',
score:100
},
{
name:'文淼',
subject:'软件工程',
score:100
}
]
var tbody=document.querySelector('tbody')
for(var i=0;i<students.length;i++){
var tr=document.createElement('tr') // 有几个人就创建几行
tbody.appendChild(tr) // 将创建的行追加到tbody的末尾
for(var key in students[i]){
var td=document.createElement('td') // 有几个属性就创建几个单元格
td.innerHTML = students[i][key]
tr.appendChild(td) // 将创建的单元格追加到每一行的末尾
}
// 创建有删除链接的单元格
var td=document.createElement('td')
td.innerHTML = '<a href="javascript:;">删除</a>'
tr.appendChild(td) // 将创建的单元格追加到每一行的末尾
}
// 删除操作
// 获取并给每一个删除超链接添加一个点击事件
var deletes=document.querySelector('tbody').querySelectorAll('a')
for(var i=0;i<deletes.length;i++){
deletes[i].onclick = function(){
// 获取删除所在的当前行
var tr=this.parentNode.parentNode // 是一个parentNode获取的是当前单元格,第二个parentNode获取的是当前行
// 删除当前行,通过父节点tbody删除
tbody.removeChild(tr)
}
}
</script>
</body>
</html>