DOM事件

277 阅读11分钟

1-addEventListener注册事件

  1.1掌握dom两种注册事件语法特点:
   (1).点语法注册事件:     事件源.事件类型 = 事件处理函数
        * 特点:不能注册‘同名事件’, 否则会覆盖

   (2).事件源.addEventListener('事件类型',事件处理函数)
        * 特点:可以注册‘同名事件’,依次触发
     addEventListener
       第一个参数:事件类型  前面不需要加 on   例如onclick直接写成click 
       第二个事件处理函数
       
       
点语法注册事件: 事件源.事件类型 = 事件处理函数
      let box = document.querySelector('#box')
       box.onclick = function () {
       alert('假如生活欺骗你')
       }
addEventListener():事件源.addEventListener('事件类型',事件处理函数)
   let box = document.querySelector('#box')
    box.addEventListener('click', function () {
        alert('我们的朋友')
    })
    box.addEventListener('click', function () {
        alert('是勤奋和努力')
    })

2-removeEventListener移除事件

    点语法注册事件:     事件源.事件类型 = 事件处理函数
      let box = document.querySelector('#box')
      box.onclick = function () {
        alert('假如生活欺骗了你')
       }
      
      移除事件
      box.onclick = null
      
      
 addEventListener()移除事件
       box.addEventListener( 'click' ,function(){
        alert('1-假如生活欺骗了你,请不要悲伤')
    } )

    function fn(){
        alert('2-请不要悲伤,因为它明天一定会继续欺骗你')
    }

    /* 
    
fn: 变量取值。 取出的是fn的地址
fn(): 函数调用。 取出的是fn的返回值
    box.addEventListener( 'click' , fn )//取出的是fn的地址和数据
    box.removeEventListener('click', fn  )
      

3-阻止默认事件

    3.1.黙认事件:html中有部分标签自带点击事件 :   form表单,a标签
    3.2.如果给这些标签注册点击事件,会默认跳转.
    黙认事件对开发影响:form表单和a标签注册点击事件,,则会(1)先执行注册点击事件
            (2)后执行黙认点击跳转业
            
3.3 阻止默认事件 : 执行自己注册的事件
e.preventDefault()
3.4.阻止默认跳转应用:如果想给form表单和a标签注册点击事件,就需要阻止默认跳转
 (1)方式一:    e.preventDefault()
                      
    获取元素
    let a = document.querySelector('a')
    let btn = document.querySelector('.btn')
    注册事件
    a.onclick = function(e){
        e.preventDefault()
        console.log('111111')
    }

    btn.onclick = function(e){
        let uname = document.querySelector('.username').value
        let pwd = document.querySelector('.password').value
        console.log( uname,pwd )
        e.preventDefault()
    }
       
       
 (2)方式二:   设置a标签的href  <a href="javascript:;"></a>
     

image.png

4. 事件对象介绍

    /* 
     1.事件对象 : 是存储与事件相关的对象。
    * 当用户触发事件的时候,浏览器会自动捕捉触发时(鼠标坐标和键盘按键)的信息,存入对象中。
      这个对象称之为事件对象。
  2.如何获取事件对象 :  给事件处理函数添加形参  event  ev  e
  3.事件对象常用属性 : 
  */
    <div id="box" style="width: 200px;
      height: 200px;background-color: red"></div>
     let box = document.querySelector('#box')
      box.onclick = function (e) {
      console.log(e);
    alert(111)
   }//点击红色盒子会弹出111
   

5. 事件对象常用属性

  1.事件对象: 存储事件相关数据
  2.事件对象语法 :
    声明: 浏览器在触发事件的时候,自动存储触发数据(鼠标坐标、键盘按键)
    取值: 给事件处理函数添加形参  e
  3.事件对象常用属性和方法
    e.pageX / e.pageY : 鼠标触发点到页面 左上角 距离
    
      <style>
          body {
          width: 3000px;
          height: 3000px;
        }

          #box {
                position: absolute;
                left: 50px;
                 top: 50px;
               }
      </style>
      </head>
      <body>
           <div id="box" style="width: 200px;
            height: 200px;background-color: red"></div>
     <script>
     let box = document.querySelector('#box')
    //注册点击事件
       box.onclick = function (e) {
       console.log(e)
    //pageX/Y : 获取鼠标触发点到 页面 左上角距离(定位坐标系)
        console.log('pageX:' + e.pageX + ' pageY:' + e.pageY)
       }
     </script>
     

image.png

案例:鼠标跟随移动
  /* 
  1.鼠标事件
    鼠标单击:onclick
    鼠标双击:ondblclick
    鼠标移入:onmouseenter
    鼠标移出:onmouseleave
    鼠标移动:onmousemove
  2.网页鼠标移动 :  window.onmousemove
  */
  img {
       position: absolute;
       left: 0;
       top: 0;
      }
      </style>
    </head>
  <body>
  <img src="./tianshi.gif" alt="" />
  <script>
     window.onmousemove = function (e) {
     //上面位置不能用body,因为body的高度由内容撑开,图片只能在图片高度的位置移动
     只能用window.onmousemove或者document.documentElement
      console.log('鼠标移出');
      console.log(e.pageX, e.pageY)
      let img = document.querySelector('img')
      //pageX是数字,赋值的时候需要在后面拼接单位'px'
         img.style.left = e.pageX + 'px'
         img.style.top = e.pageY + 'px'
        }
     </script>
     

image.png

window.onmousemove 获取整个窗口

document.documentElement 获取dom树下的根元素html

6.键盘事件及获取按键

  1.键盘事件总结
    oninput:键盘输入(一般用于实时获取输入框'内容'')
    onfocus:键盘成为焦点
    onblur:键盘失去焦点
    onkeydown:键盘按下(一般用于获取按键)
    onkeyup:键盘松开
 2.如何获取用户按键
    e.key:按键字串
    e.keyCode:键盘ASCII码(键盘上的每一个按键对应一个数字,称之为ASCII码)
    确认键ASCII码:13
    document.querySelector('input').onkeydown = function (e) {
      console.log(e);
      console.log(e.key, e.keyCode)
      if (e.key == 'Enter') {
      alert('用户按了enter键')
     }
   // keyCode : enter的ascii码
      if (e.keyCode == 13) {
      console.log('执行搜索功能')
      }
      }
     document.querySelector('input').onkeyup = function () {
  // console.log('2-键盘松开')
  

image.png image.png

7. 事件冒泡介绍

   1.事件冒泡: 当触发子元素的事件时,该子元素的所有“父级元素” 的“同名事件”会依次触发 
        * 事件冒泡现象一直都存在,只是以前没有给父元素注册同名事件
        * 子元素 -> 父元素 -> body -> html -> document -> window 
        子元素
       document.querySelector('.son').addEventListener('click', function () {
         alert('我是子元素')
        })
       父元素
      document.querySelector('.father').addEventListener('click', function () {
        alert('我是父元素')
        })
    body
      document.body.addEventListener('click', function () {
       alert('我是body')
       })
    html
     document.documentElement.addEventListener('click', function () {
       alert('我是html')
      })
   document
        document.addEventListener('click', function () {
          alert('我是document')
        })
  window
        document.addEventListener('click', function () {
           alert('我是window')
       })

image.png

8.事件委托

  (1).事件委托 :给"动态新增"元素注册事件
  (2)什么是事件委托:给父元素注册事件,委托子元素处理
  (3) 事件委托原理:事件冒泡
  (4)事件委托注意点:
      this:不能使用.this指向父元素
      e.target:推荐使用.事件目标指向触发冒泡的子元素
需求: 点击按钮,新增li元素,并且点击新增li元素的内容,改变新增内容的颜色
 <button class="btn">点我新增一行li元素</button>
  <ul>
    <li>我是班长1</li>
    <li>我是班长2</li>
    <li>我是班长3</li>
    <li>我是班长4</li>
    <li>我是班长5</li>
    <li>我是班长6</li>
 </ul>
(1)点击按钮,新增li元素
    document.querySelector('.btn').onclick = function () {
     创建空标签
  let newLi = document.createElement('li')
    设置内容
  newLi.innerText = '我是新来的'
    添加到ul
  document.querySelector('ul').appendChild(newLi)
}
   事件委托:给父元素注册事件,委托子元素处理
document.querySelector('ul').onclick = function (e) {
     this:父元素ul
  console.log(this);
     e : 事件对象
  console.log(e);
     e.target:事件目标(点哪一个li触发的冒泡)
    e.target.style.backgroundColor = 'pink'
}

image.png

9. 事件捕获

 1.事件捕获 : 当触发子元素的事件时候,先从最顶级父元素,一级一级往里触发
    1.1 规则:  window->document->html->body->父元素->子元素

  2.默认情况下,所有的注册事件都是冒泡事件。 只有唯一一种方式可以注册捕获事件:
    元素.addEventListener('事件类型',事件处理函数,true)
    <style>
  .father {
    width: 300px;
    height: 300px;
    background-color: red;
  }

  .son {
    width: 100px;
    height: 100px;
    background-color: cyan;
  }
</style>
  </head>
  <body>
   <div class="father">
    <div class="son"></div>
   </div>

   <script>
   //子元素
  document.querySelector('.son').addEventListener('click',function(){
    alert('我是蓝色子元素')
  },true)

  //父元素
  document.querySelector('.father').addEventListener('click',function(){
    alert('我是红色父元素')
  },true)

   //body
   document.body.addEventListener('click',function(){
    alert('我是body')
  },true)

  //html
  document.documentElement.addEventListener('click',function(){
    alert('我是html')
  },true)

  //document
  document.addEventListener('click',function(){
    alert('我是document')
  },true)

  //window
  window.addEventListener('click',function(){
    alert('我是window')
  },true)

10.事件流三个阶段

 事件流三个阶段:  e.eventPhase
    1-捕获阶段
    2-目标阶段
    3-冒泡阶段
      //子元素
// document.querySelector('.son').addEventListener('click',function(e){
//   alert('我是蓝色子元素' + e.eventPhase )
// },false)//冒泡

//父元素
document.querySelector('.father').addEventListener('click', function (e) {
  alert('我是红色父元素' + e.eventPhase)
}, false)

//body
document.body.addEventListener('click', function (e) {
  alert('我是body' + e.eventPhase)
}, false)

//html
document.documentElement.addEventListener('click', function (e) {
  alert('我是html' + e.eventPhase)
}, false) //冒泡

//document
document.addEventListener('click', function (e) {
  alert('我是document' + e.eventPhase)
}, true) //捕获

//window
window.addEventListener('click', function (e) {
  alert('我是window' + e.eventPhase)
}, true) //捕获

11. 阻止事件流动

       阻止事件流动 :e.stopPropagation()
     无论是冒泡还是捕捉都可以阻止(停止事件流)
      //子元素
document.querySelector('.son').addEventListener('click', function (e) {
  alert('我是蓝色子元素' + e.eventPhase)
}, false) //冒泡

//父元素
document.querySelector('.father').addEventListener('click', function (e) {
  alert('我是红色父元素' + e.eventPhase)

}, false)

//body
document.body.addEventListener('click', function (e) {
  alert('我是body' + e.eventPhase)
}, false)

//html
document.documentElement.addEventListener('click', function (e) {
  alert('我是html' + e.eventPhase)
}, false) //冒泡

//document
document.addEventListener('click', function (e) {
  alert('我是document' + e.eventPhase)

}, true) //捕获

//window
window.addEventListener('click', function (e) {
  alert('我是window' + e.eventPhase)
  e.stopPropagation()
}, true) //捕获

12.案例:排他思想---循环排他(万能的)

  <body>
    <button>按钮1</button>
    <button>按钮2</button>
    <button>按钮3</button>
    <button>按钮4</button>
    <button>按钮5</button>

<script>
/* 
1.排他思想场景 : 多个元素,只能选中一个(多选一)
2.排他思想流程 :(1)干掉所有兄弟  (2)复活自己
*/

//1.获取页面元素
let buttonList = document.querySelectorAll('button')
//2.给每一个按钮注册点击事件
for (let i = 0; i < buttonList.length; i++) {//i = 0 1 2 3 4
  buttonList[i].onclick = function () {
    /* 
    i : 你点击的按钮下标
    buttonList[i] : 你点击的按钮
    this === buttonList[i]: 你点击的按钮
    */
    console.log(i, buttonList[i], this)

    //排他思想 两个步骤
    //(1)干掉所有兄弟
    for (let j = 0; j < buttonList.length; j++) {
      buttonList[j].style.backgroundColor = ''
    }
    //(2)复活自己
    this.style.backgroundColor = 'pink'
  }
}
 </script>
 </body> 
 

image.png

image.png

13.案例 搜索框

  <style>
    * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    }

    ul {
        list-style: none;
    }

    .mi {
        position: relative;
        width: 223px;
        margin: 100px auto;
    }

    .mi input {
        width: 223px;
        height: 48px;
        padding: 0 10px;
        font-size: 14px;
        line-height: 48px;
        border: 1px solid #e0e0e0;
        outline: none;
    }

    .mi .search {
        border: 1px solid #ff6700;
    }

    .result-list {
        position: absolute;
        left: 0;
        top: 48px;
        width: 223px;
        border: 1px solid #ff6700;
        border-top: 0;
        background: #fff;
    }

    .result-list a {
        display: block;
        padding: 6px 15px;
        font-size: 12px;
        color: #424242;
        text-decoration: none;
    }

    .result-list a:hover {
        background-color: #eee;
    }
</style>
 </head>

 <body>
      <div class="mi">
           <input type="search" placeholder="小米笔记本" />
           <ul class="result-list" style="display: none">
                <li><a href="#">全部商品</a></li>
                <li><a href="#">小米11</a></li>
                <li><a href="#">小米10S</a></li>
                <li><a href="#">小米笔记本</a></li>
                <li><a href="#">小米手机</a></li>
                <li><a href="#">黑鲨4</a></li>
                <li><a href="#">空调</a></li>
         </ul>
    </div>
<script>
      const input = document.querySelector('input')
      const ul = document.querySelector('.result-list')
       input.addEventListener('focus', function () {
        input.classList.add('search')
        ul.style.display = 'block'
    })
    input.addEventListener('blur', function () {
        input.classList.remove('search')
        ul.style.display = 'none'
    })
</script>

image.png

14.案例 随机点名

 <style>
    * {
        margin: 0;
        padding: 0;
    }

    h2 {
        text-align: center;
    }

    .box {
        width: 600px;
        margin: 50px auto;
        display: flex;
        font-size: 25px;
        line-height: 40px;
    }

    .qs {

        width: 450px;
        height: 40px;
        color: red;

    }

    .btns {
        text-align: center;
    }

    .btns button {
        width: 120px;
        height: 35px;
        margin: 0 50px;
    }
</style>
</head>

<body>
<h2>随机点名</h2>
<div class="box">
    <span>名字是:</span>
    <div class="qs">这里显示姓名</div>
</div>
<div class="btns">
    <button class="start">开始</button>
    <button class="end">结束</button>
</div>

<script>
    // 数据数组
    const arr = ['马超', '黄忠', '赵云', '关羽', '张飞']
    let id
    let i

    function getRandom(min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值 
    }
    //获取标签
    const start = document.querySelector('.start')
    const qs = document.querySelector('.qs')
    //给开始按钮注册事件
    start.addEventListener('click', function () {
        if (id) clearInterval(id)
        //开始定时器
        id = setInterval(function () {
            i = getRandom(0, arr.length - 1)
            qs.innerHTML = arr[i]
        }, 100)
        //判断数组的长度,当长度等于1时就禁用开始按钮和结束按钮
        if (arr.length === 1) {
            start.disabled = true
            end.disabled = true
        }
    })
    //获取结束标签
    const end = document.querySelector('.end')
    //给结束按钮注册事件
    end.addEventListener('click', function () {
            //停止定时器
            clearInterval(id)
            //删除这个补选中的元素
            arr.splice(i, 1)
        }

    )
</script>

image.png

15.案例 全选反选

<style>
* {
  margin: 0;
  padding: 0;
}

table {
  border-collapse: collapse;
  border-spacing: 0;
  border: 1px solid #c0c0c0;
  width: 500px;
  margin: 100px auto;
  text-align: center;
}

th {
  background-color: #09c;
  font: bold 16px "微软雅黑";
  color: #fff;
  height: 24px;
}

td {
  border: 1px solid #d0d0d0;
  color: #404060;
  padding: 10px;
}

.allCheck {
  width: 80px;
}
 </style>
 </head>
<body>
<table>
<tr>
  <th class="allCheck">
    <input type="checkbox" name="" id="checkAll"> <span class="all">全选</span>
  </th>
  <th>商品</th>
  <th>商家</th>
  <th>价格</th>
</tr>
<tr>
  <td>
    <input type="checkbox" name="check" class="ck">
  </td>
  <td>小米手机</td>
  <td>小米</td>
  <td>¥1999</td>
</tr>
<tr>
  <td>
    <input type="checkbox" name="check" class="ck">
  </td>
  <td>小米净水器</td>
  <td>小米</td>
  <td>¥4999</td>
</tr>
<tr>
  <td>
    <input type="checkbox" name="check" class="ck">
  </td>
  <td>小米电视</td>
  <td>小米</td>
  <td>¥5999</td>
</tr>
 </table>
 <script>
//获取元素
const checkAll = document.querySelector('#checkAll')
const ck = document.querySelectorAll('.ck')
//给最上面的盒子注册事件
checkAll.addEventListener('click', function () {
  //循环每一个小盒子
  for (let i = 0; i < ck.length; i++) {
    ck[i].checked = checkAll.checked
  }
})
for (let i = 0; i < ck.length; i++) {
  //给下面的盒子注册点击事件
  ck[i].addEventListener('click', function () {
    //获取下面盒子的元素的长度(借助css选择器:checked)
    const ckLength = document.querySelectorAll('.ck:checked').length
    checkAll.checked = ckLength === ck.length
  })
}
 </script>
 

image.png

16.评论回车发布

<style>
.wrapper {
  min-width: 400px;
  max-width: 800px;
  display: flex;
  justify-content: flex-end;
}

.avatar {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  overflow: hidden;
  background: url(./images/avatar.jpg) no-repeat center / cover;
  margin-right: 20px;
}

.wrapper textarea {
  outline: none;
  border-color: transparent;
  resize: none;
  background: #f5f5f5;
  border-radius: 4px;
  flex: 1;
  padding: 10px;
  transition: all 0.5s;
  height: 30px;
}

.wrapper textarea:focus {
  border-color: #e4e4e4;
  background: #fff;
  height: 50px;
}

.wrapper button {
  background: #00aeec;
  color: #fff;
  border: none;
  border-radius: 4px;
  margin-left: 10px;
  width: 70px;
  cursor: pointer;
}

.wrapper .total {
  margin-right: 80px;
  color: #999;
  margin-top: 5px;
  opacity: 0;
  transition: all 0.5s;
}

.list {
  min-width: 400px;
  max-width: 800px;
  display: flex;
}

.list .item {
  width: 100%;
  display: flex;
}

.list .item .info {
  flex: 1;
  border-bottom: 1px dashed #e4e4e4;
  padding-bottom: 10px;
}

.list .item p {
  margin: 0;
}

.list .item .name {
  color: #FB7299;
  font-size: 14px;
  font-weight: bold;
}

.list .item .text {
  color: #333;
  padding: 10px 0;
}

.list .item .time {
  color: #999;
  font-size: 12px;
}
 </style>
 </head>

<body>
 <div class="wrapper">
<i class="avatar"></i>
<textarea id="tx" placeholder="发一条友善的评论" rows="2" maxlength="200"></textarea>
<button>发布</button>
  </div>
 <div class="wrapper">
<span class="total">0/200字</span>
 </div>
  <div class="list">
<div class="item" style="display: none;">
  <i class="avatar"></i>
  <div class="info">
    <p class="name">清风徐来</p>
    <p class="text">大家都辛苦啦,感谢各位大大的努力,能圆满完成真是太好了[笑哭][支持]</p>
    <p class="time">2022-10-10 20:29:21</p>
  </div>
</div>
 </div>

 <script>
const tx = document.querySelector('#tx')
const total = document.querySelector('.total')
tx.addEventListener('focus', function () {
  total.style.opacity = 1
})
tx.addEventListener('blur', function () {
  total.style.opacity = 0
})
tx.addEventListener('input', function () {
  const length = tx.value.length
  total.innerHTML = `${length}/200字`
})
//获取button元素,以及item元素text元素
const button = document.querySelector('button')
const item = document.querySelector('.item')
const text = document.querySelector('.text')
//给按钮注册点击事件
button.addEventListener('click', function () {
  //获得文本框的内容
  const val = tx.value.trim()
  if (val.length === 0) {
    alert('没有输入内容')
  } else {
    //让item盒子显示出来
    item.style.display = 'block'
    //把输入的内容写到text盒子里面
    text.innerHTML = tx.value
    tx.value = ''

  }
})
tx.addEventListener('keydown', function (e) {
  if (e.key === 'Enter') {
    button.click()
  }
})
</script>

image.png

17.点击关闭广告

<style>
    .box {
         position: relative;
         width: 1000px;
         height: 200px;
         background-color: pink;
         margin: 100px auto;
         text-align: center;
         font-size: 50px;
         line-height: 200px;
         font-weight: 700;
      }

   .close {
           position: absolute;
           right: 20px;
           top: 10px;
           width: 20px;
           height: 20px;
           background-color: skyblue;
           text-align: center;
           line-height: 20px;
           font-size: 16px;
           cursor: pointer;
         }
 </style>
</head>
  <body>
       <div class="box">
          我是广告
       <div class="close">X</div>
      </div>
  <script>
          const close1 = document.querySelector('.close')
          const box = document.querySelector('.box')
           close1.addEventListener('click', function () {
           box.style.display = 'none'
      })
  </script>
  

image.png

18.tab栏切换----循环排他(万能的)

<style>
 .Box {
      width: 240px;
      border: 1px solid #000;
      margin: 100px auto;
      padding: 20px;
    }

  .con {
       width: 100%;
       height: 200px;
       background-color: #cccccc;
       border: 1px solid #000;
       margin-top: 10px;
      display: none;
    }

 .current {
           background-color: pink;
           border: 2px black solid;
   }
 </style>
</head>

<body>
    <div class="Box" id="box">
    <button>按钮1</button>
    <button>按钮2</button>
    <button>按钮3</button>
    <button>按钮4</button>
    <div class="con" style="display:block">内容1</div>
    <div class="con">内容2</div>
    <div class="con">内容3</div>
    <div class="con">内容4</div>
</div>

 <script>
1.排他思想应用场景 : 多个元素只能选中一个元素的场景
2.排他思想实现思路:两种思路
  循环排他(万能的)         : (1)循环干掉所有兄弟  (2)复活自己
  类名排他(一定要有类名)   :  (1)使用类选择器干掉选中的兄弟  (2)复活自己

总结:  元素有类名就用类名排他, 没有类名就用 循环排他。 切记两者不可混用
  类名排他: 通过classList类名修改样式
  循环排他: 通过style修改样式   
  
3.tab栏切换(选项卡)  =  两个排他

//1.获取元素
let buttonList = document.querySelectorAll('button')
let conList = document.querySelectorAll('.con')

//2.注册事件
for (let i = 0; i < buttonList.length; i++) {
  buttonList[i].addEventListener('click', function () {
    //3.事件处理 : 循环排他
    console.log(i, this) //自己的下标,自己
    //(1)循环干掉所有兄弟
    for (let j = 0; j < buttonList.length; j++) {
      buttonList[j].style.backgroundColor = ''
      conList[j].style.display = 'none'
    }
    //(2)复活自己
    buttonList[i].style.backgroundColor = 'pink'
    conList[i].style.display = 'block'

  })
}
</script>

image.png

19.隔行变色高级版---鼠标经过时会变成红色

 <body>
     <ul>
         <li>我是班长1</li>
         <li>我是班长2</li>
         <li>我是班长3</li>
         <li>我是班长4</li>
         <li>我是班长5</li>
         <li>我是班长6</li>
         <li>我是班长7</li>
         <li>我是班长8</li>
         <li>我是班长9</li>
         <li>我是班长10</li>
     </ul>

<script>
/* 1.设置每一个li元素颜色: 单绿 双黄
    2.鼠标移入li元素: 颜色变红
    3.鼠标移出li元素: 颜色恢复原先的颜色
  */

let liList = document.querySelectorAll('li')

for (let i = 0; i < liList.length; i++) {
  //1.设置颜色
  liList[i].style.backgroundColor = i % 2 == 0 ? 'green' : 'yellow'
  //2.鼠标移入
  liList[i].addEventListener('mouseenter', function () {
    //先存储当前颜色
    this.setAttribute('bgc', this.style.backgroundColor)
    //后修改红色
    this.style.backgroundColor = 'red'
  })
  //3.鼠标移出
  liList[i].addEventListener('mouseleave', function () {
    //取出自定义属性的值 赋值给 背景颜色
    this.style.backgroundColor = this.getAttribute('bgc')
  })
}
 </script>

image.png

image.png

20.案例:图片切换

<style>
.title {
  background-color: skyblue;
  color: white;
}

img {
  width: 200px;
  height: 200px;
  box-shadow: 0 0 20px hotpink;
}
</style>
</head>

<body>
  <h2 class="title">图片切换</h2>
  <img alt="" src="./images/01.jpg" />
  <br />
 <input id="prev" type="button" value="上一张" />
 <input id="next" type="button" value="下一张" />

<script>

/*思路分析 
0. 图片切换类功能一定要声明  全局变量index  存储下标
  (1)为什么要声明变量: 因为下一页需要让下标自增, 而字面量0是无法自增 0++(程序报错),
  =左边只能是变量
  (2)为什么要是全局变量:因为下一页 和 上一页 事件处理函数 是两个不同的局部作用域。
   要想变量在任何地方都能使用, 就必须要是全局变量

 1.点击下一张 :     
 2.点击上一张 :
//多个数据 使用数组存储
let imgArr = [
  "./images/01.jpg",
  "./images/02.jpg",
  "./images/03.jpg",
  "./images/04.jpg",
  "./images/05.jpg",
]

//1.声明'全局变量'记录下标
let index = 0
//获取元素
let img = document.querySelector("img")
let prev = document.querySelector("#prev")
let next = document.querySelector("#next")

//2.1 下一页
next.onclick = function () {
  //3.1 无限切换思路  
  //(1)如果index是最后一张下标 == 数组长度-1 ,则 index = 0  (2)否则index++
  // if( index == imgArr.length-1 ){
  //   index = 0
  // }else{
  //   index++
  // }
  //三元表达式    表达式?代码1:代码2
  index == imgArr.length-1 ? index = 0 : index++
  //3.2 修改img标签的src
  img.src = imgArr[index]
}

//2.2 上一页
prev.onclick = function () {
  //3.1 下标自减 (1)如果index是第一张 == 0,则index=数组长度-1 (2)否则index--
  index == 0 ? index = imgArr.length-1 : index--
  //3.2 修改img标签的src
  img.src = imgArr[index]
}
 </script>
 </body>
 

image.png

image.png

21.突出展示

 <style type="text/css">
  * {
    margin: 0;
    padding: 0;
  }

  ul {
    list-style: none;
    padding: 0;
    margin: 0;
  }

  body {
    background: #000;
  }

  .wrap {
    margin: 100px auto 0;
    width: 630px;
    height: 394px;
    padding: 5px;
    background: #000;
    overflow: hidden;
    border: 1px solid #fff;
  }

  .wrap li {
    float: left;
    padding: 5px;
  }

  .wrap img {
    display: block;
    border: 0;
  }
</style>
 </head>

 <body>
<div class="wrap">
  <ul>
    <li>
      <a href="#"><img src="images/01.jpg" alt=""/></a>
    </li>
    <li>
      <a href="#"><img src="images/02.jpg" alt=""/></a>
    </li>
    <li>
      <a href="#"><img src="images/03.jpg" alt=""/></a>
    </li>
    <li>
      <a href="#"><img src="images/04.jpg" alt=""/></a>
    </li>
    <li>
      <a href="#"><img src="images/05.jpg" alt=""/></a>
    </li>
    <li>
      <a href="#"><img src="images/06.jpg" alt=""/></a>
    </li>
  </ul>
</div>

<script>
  /* 鼠标移入每一个li元素 : 排他思想
    (1)干掉兄弟: opacity:0.5   (2)复活自己: opacity:1
  */

  //1.获取
  let liList = document.querySelectorAll('li')
  //2.给每一个li元素注册鼠标移入事件
  for(let i = 0;i<liList.length;i++){
    liList[i].onmouseenter = function(){
      //3.排他
      //(1)干掉兄弟
      for(let j = 0;j<liList.length;j++){
        liList[j].style.opacity = 0.5
      }
      //(2)复活自己  this
      this.style.opacity = 1
    }
  }
</script>
</body>

image.png

22.排他思想升级---类名排他(一定要有类名)

 <style>
  .pink {
    background-color: pink;
  }
</style>
</head>
<body>
<button class="pink">按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>

<script>
  /* 
  1.排他思想应用场景 : 多个元素只能选中一个元素的场景
  2.排他思想实现思路:两种思路
    循环排他(万能的)         : (1)循环干掉所有兄弟  (2)复活自己
    类名排他(一定要有类名)   :  (1)使用类选择器干掉选中的兄弟  (2)复活自己

  总结:  元素有类名就用类名排他, 没有类名就用 循环排他。 切记两者不可混用
    类名排他: 通过classList类名修改样式
    循环排他: 通过style修改样式        
  */

  //1.获取元素
  let buttonList = document.querySelectorAll('button')
  //2.给每一个按钮注册点击事件
  for(let i = 0;i<buttonList.length;i++){
    buttonList[i].onclick = function(){
      //3.事件处理:排他
      //(1)使用类选择器干掉选中的兄弟
      document.querySelector('.pink').classList.remove('pink')
      //(2)复活自己
      this.classList.add('pink')
    }
  }
</script>
</body>

image.png image.png

23.tab栏切换---类名排他(一定要有类名)

 <style type="text/css">
  * {
    margin: 0;
    padding: 0;
  }
  ul {
    list-style: none;
  }
  .wrapper {
    width: 1000px;
    height: 475px;
    margin: 0 auto;
    margin-top: 100px;
  }
  .tab {
    border: 1px solid #ddd;
    border-bottom: 0;
    height: 36px;
    width: 320px;
  }
  .tab li {
    position: relative;
    float: left;
    width: 80px;
    height: 34px;
    line-height: 34px;
    text-align: center;
    cursor: pointer;
    border-top: 4px solid #fff;
  }
  .tab span {
    position: absolute;
    right: 0;
    top: 10px;
    background: #ddd;
    width: 1px;
    height: 14px;
    overflow: hidden;
  }
  .products {
    width: 1002px;
    border: 1px solid #ddd;
    height: 476px;
  }
  .products .main {
    float: left;
    display: none;
  }
  .products .main.selected {
    display: block;
  }
  .tab li.active {
    border-color: red;
    border-bottom: 0;
  }
</style>
</head>
<body>
<div class="wrapper">
  <ul class="tab">
    <li class="tab-item active">国际大牌<span></span></li>
    <li class="tab-item">国妆名牌<span></span></li>
    <li class="tab-item">清洁用品<span></span></li>
    <li class="tab-item">男士精品</li>
  </ul>
  <div class="products">
    <div class="main selected">
      <a href="###"><img src="images/guojidapai.jpg" alt=""/></a>
    </div>
    <div class="main">
      <a href="###"><img src="images/guozhuangmingpin.jpg" alt=""/></a>
    </div>
    <div class="main">
      <a href="###"><img src="images/qingjieyongpin.jpg" alt=""/></a>
    </div>
    <div class="main">
      <a href="###"><img src="images/nanshijingpin.jpg" alt=""/></a>
    </div>
  </div>
</div>
<script>
  /* 点击上方li元素
        1.tab栏 = 两个排他
          上面类名排他 :  active
          下面类名排他 :  selected
  */
  //1.获取元素
  let liList = document.querySelectorAll('.tab-item')
  let mainList = document.querySelectorAll('.main')

  //2.点击每一个li元素
  for(let i = 0;i<liList.length;i++){
    liList[i].onclick = function(){
      //3. 类名排他
      //3.1 上面排他
      document.querySelector('.active').classList.remove('active')
      liList[i].classList.add('active')
      //3.2 下面排他
      document.querySelector('.selected').classList.remove('selected')
      mainList[i].classList.add('selected')
    }
  }
</script>
</body>

image.png

24.开关思想

 <body>
 <script>
    /* 
    1.排他思想 :  多个元素,只能选中一个(多选一)
        循环排他 : (1)循环干掉所有兄弟 (2)复活自己   
            语法:  元素.style.样式名 = 样式值
        类名排他:  (1)类选择器干掉上一次选中兄弟 (2)复活自己 
            语法:  元素.classList.add(类名)

    2.开关思想 :  判断数组中 是否所有元素都满足条件
        (1)声明布尔类型开关变量   let bol = true
        (2)遍历数组,检测开关变量是否成立 : 找false
        (3)获取开关变量的值
    */    

    //需求:判断数组中元素 是不是都大于10
    let arr = [20,50,80,90,55]

    //(1) 声明布尔类型开关变量   let bol = true
    let bol = true
    //(2) 遍历数组,检测开关变量是否成立 : 找false
    for(let i = 0;i<arr.length;i++){
        // 检测开关变量是否成立 : 找false
        if( arr[i] < 10 ){
            bol = false
            break
        }
    }
    //(3) 获取开关变量的值
    console.log(bol)//true
</script>
</body>

25.案例:全选与反选

<style>
* {
  margin: 0;
  padding: 0;
}

table {
  border-collapse: collapse;
  border: 1px solid #c0c0c0;
  width: 500px;
  margin: 100px auto;
  text-align: center;
}

th {
  background-color: #09c;
  font: bold 16px '微软雅黑';
  color: #fff;
  height: 24px;
}

td {
  border: 1px solid #d0d0d0;
  color: #404060;
  padding: 10px;
}
</style>
</head>

<body>
 <table>
 <tr>
  <th><input type="checkbox" id="checkAll" />全选/全不选</th>
  <th>菜名</th>
  <th>商家</th>
  <th>价格</th>
</tr>
<tr>
  <td>
    <input type="checkbox" class="check" />
  </td>
  <td>红烧肉</td>
  <td>隆江猪脚饭</td>
  <td>¥200</td>
</tr>
<tr>
  <td>
    <input type="checkbox" class="check" />
  </td>
  <td>香酥排骨</td>
  <td>隆江猪脚饭</td>
  <td>¥998</td>
</tr>
<tr>
  <td>
    <input type="checkbox" class="check" />
  </td>
  <td>北京烤鸭</td>
  <td>隆江猪脚饭</td>
  <td>¥88</td>
</tr>
</table>

 <script>
/* 思路分析
  1.点击每一个单选框: 开关思想 判断数组每一个元素是否选中  ( checked值为true )

  2.点击全选框 : 设置每一个单选框的checked值与 全选框 一致
    一致: 全选为true,单选框也要为true.  全选为false,单选框为false
*/

//1.获取元素
let checkList = document.querySelectorAll('.check')//单选框数组
let checkAll = document.querySelector('#checkAll')//全选框

//2.点击每一个单选框
for (let i = 0; i < checkList.length; i++) {
  checkList[i].onclick = function () {
    //3.开关思想 判断数组每一个元素是否选中  ( checked值为true )
    //(1)声明开关变量,默认值为true
    let bol = true
    //(2)遍历数组检测开关变量:找false
    for (let j = 0; j < checkList.length; j++) {
      if ( !checkList[j].checked ) {
        bol = false
        break
      }
    }
    //(3)获取开关变量结果
    // console.log(bol)
    checkAll.checked = bol
    // if( bol ){
    //   checkAll.checked = true
    // }else{
    //   checkAll.checked = false
    // }
  }
}

//2.2 点击全选框
checkAll.onclick = function(){
  //this : 全选框checkAll
  console.log( this.checked )
  //3. 设置每一个单选框的checked值与 全选框一致
  for(let i = 0;i<checkList.length;i++){
    checkList[i].checked = this.checked
  } 
}
 </script>
 </body>
 

image.png

案例第二种方法:

image.png

image.png

案例介绍

image.png

image.png

image.png

image.png

26.attribute语法及属性

image.png image.png

27.隔行变色高级版

<body>
<ul>
  <li>我是班长1</li>
  <li>我是班长2</li>
  <li>我是班长3</li>
  <li>我是班长4</li>
  <li>我是班长5</li>
  <li>我是班长6</li>
  <li>我是班长7</li>
  <li>我是班长8</li>
  <li>我是班长9</li>
  <li>我是班长10</li>
</ul>

<script>
  /* 1.设置每一个li元素颜色: 单绿 双黄
    2.鼠标移入li元素: 颜色变红
    3.鼠标移出li元素: 颜色恢复原先的颜色
  */
  //1.获取所有li元素
  let liList = document.querySelectorAll('li')

  //2.遍历数组
  for(let i = 0;i<liList.length;i++){
    //2.1 设置颜色
    liList[i].style.backgroundColor = (i % 2 == 0 ? 'green' : 'yellow')
    //2.2 鼠标移入
    liList[i].onmouseenter = function(){
      //3.1 先存储当前的颜色
      this.setAttribute('aaa', this.style.backgroundColor )
      //3.2 修改颜色
      this.style.backgroundColor = 'red'
    }
    //2.3 鼠标移出
    liList[i].onmouseleave = function(){
      //3.恢复原来的颜色
      this.style.backgroundColor = this.getAttribute('aaa')
    }
  } 
</script>
</body>

image.png

image.png

image.png

28.案例

<style>
* {
  margin: 0;
  padding: 0;
}

a {
  text-decoration: none;
  color: #721c24;
}

h1 {
  text-align: center;
  color: #333;
  margin: 20px 0;
}

table {
  margin: 0 auto;
  width: 800px;
  border-collapse: collapse;
  color: #004085;
}

th {
  padding: 10px;
  background: #cfe5ff;

  font-size: 20px;
  font-weight: 400;
}

td,
th {
  border: 1px solid #b8daff;
}

td {
  padding: 10px;
  color: #666;
  text-align: center;
  font-size: 16px;
}

tbody tr {
  background: #fff;
}

tbody tr:hover {
  background: #e1ecf8;
}

.info {
  width: 900px;
  margin: 50px auto;
  text-align: center;
}

.info input {
  width: 80px;
  height: 25px;
  outline: none;
  border-radius: 5px;
  border: 1px solid #b8daff;
  padding-left: 5px;
}

.info button {
  width: 60px;
  height: 25px;
  background-color: #004085;
  outline: none;
  border: 0;
  color: #fff;
  cursor: pointer;
  border-radius: 5px;
}

.info .age {
  width: 50px;
}
</style>
</head>

<body>
     <h1>新增学员</h1>
    <form action="">
<div class="info">
  姓名:<input type="text" class="uname" /> 年龄:<input type="text"
  class="age" />
  性别:
  <select name="gender" id="" class="gender">
    <option value="男"></option>
    <option value="女"></option>
  </select>
  薪资:<input type="text" class="salary" /> 就业城市:<select name="city"
  id="" class="city">
    <option value="北京">北京</option>
    <option value="上海">上海</option>
    <option value="广州">广州</option>
    <option value="深圳">深圳</option>
    <option value="曹县">曹县</option>
  </select>
  <button class="add">录入</button>
</div>
</form>

   <h1>就业榜</h1>
  <table>
   <thead>
   <tr>
    <th>学号</th>
    <th>姓名</th>
    <th>年龄</th>
    <th>性别</th>
    <th>薪资</th>
    <th>就业城市</th>
    <th>操作</th>
  </tr>
</thead>
<tbody>
  <!-- <tr>
      <td>1001</td>
      <td>欧阳霸天</td>
      <td>19</td>
      <td>男</td>
      <td>15000</td>
      <td>上海</td>
      <td>
        <a href="javascript:" class="delete">删除</a>
      </td>
    </tr> -->
</tbody>
</table>
 <script>
//准备好数据后端的数据
let arr = [
  {
    stuId: 1001,
    uname: '欧阳霸天',
    age: 19,
    gender: '男',
    salary: '20000',
    city: '上海'
  },
  {
    stuId: 1002,
    uname: '令狐霸天',
    age: 29,
    gender: '男',
    salary: '30000',
    city: '北京'
  },
  {
    stuId: 1003,
    uname: '诸葛霸天',
    age: 39,
    gender: '男',
    salary: '2000',
    city: '北京'
  }
]


//1.把数组中的元素 显示到页面

for (let i = 0; i < arr.length; i++) {
  //(1)创建空标签 
  let tr = document.createElement('tr')
  //(2)设置内容
  tr.innerHTML = `<td>1001</td>
      <td>${arr[i].uname}</td>
      <td>${arr[i].age}</td>
      <td>${arr[i].gender}</td>
      <td>${arr[i].salary}</td>
      <td>${arr[i].city}</td>
      <td>
        <a href="javascript:" class="delete">删除</a>
      </td>`
  //(3)添加到tbody
  document.querySelector('tbody').appendChild(tr)
}


/* 2.点击录入 : 表单中的按钮需要阻止默认跳转
    2.1 非空判断 : 输入框文本不能为空
    2.2 新增元素
      (1)创建空标签
      (2)设置内容
      (3)添加到tbody
    2.3 清空表单
*/

 let uname = document.querySelector('.uname') 
 let age = document.querySelector('.age') 
 let gender = document.querySelector('.gender') 
 let salary = document.querySelector('.salary') 
 let city = document.querySelector('.city') 

 document.querySelector('.add').onclick = function(e){
 //(0)阻止表单默认跳转
 e.preventDefault()
 //(1)非空判断 : 如果有空,不能添加
 if( uname.value == '' || age.value == '' || salary.value == '' ){
    alert('输入框不能为空')
    return
 }
 //(2)创建tr
 //创建空标签 
 let tr = document.createElement('tr')
  //设置内容
  tr.innerHTML = `<td>1001</td>
      <td>${uname.value}</td>
      <td>${age.value}</td>
      <td>${gender.value}</td>
      <td>${salary.value}</td>
      <td>${city.value}</td>
      <td>
        <a href="javascript:" class="delete">删除</a>
      </td>`
  //添加到tbody
  document.querySelector('tbody').appendChild(tr)

  //(3)清空表单
  /* 如果是单个input :  input.value = ''
     如果是form表单 :   form.reset()
  */
   document.querySelector('form').reset()   

  }

  /* 3.点击删除 : 删除是动态新增元素,需要注册委托事件
   (1)事件委托 :  给父元素注册, 委托子元素处理
 * 父元素也不能是新增的,如果分不清楚,可以直接给body注册
   (2)事件委托注意点:
       不能用this : 指向事件源(父元素)
       用e.target : 指向事件目标 (触发本次冒泡的子元素)
   */

  //事件: 给父元素注册
     document.body.onclick = function(e){
      console.log(e.target)
  //委托: 找到委托的子元素: 判断到底是不是删除按钮
if( e.target.classList.contains('delete') ){
  /* 
  e.target : 删除按钮
  e.target.parentNode : td
  e.target.parentNode.parentNode : tr
  */
  document.querySelector('tbody').removeChild( e.target.parentNode.parentNode )
}
}

image.png