jsの再体验 - - DOM(Web APIs 页面文档对象模型)

一、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>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值