J54 DOM事件

239 阅读5分钟

1.DOM事件的基础知识

1、事件网址:developer.mozilla.org/zh-CN/docs/…
2.查看元素的属性(属性中onxxx就是元素拥有的事件行为)查看事件,控制台:dir(某个dom元素,如:box)
3.事件:是元素天生自带的默认行为

不论我们是否给绑定了方法,当我们操作的时候,也会把对应的事件触发

4.事件绑定:是给元素的某个行为绑定一个方法

目的是当事件行为触发的时候,会把对应的方法执行

5.获取元素的映射机制
  • 1.getElementsByTagName:有映射机制
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>鼠标事件</title>
   </head>
<body> 
 <ul id=ul_box>
     <li>1</li>
     <li>2</li>
     <li>3</li>
     <li>4</li>
 </ul>
    <script>
    /* 获取元素的映射机制
     * getElementsByTagName:有映射机制
     */
    var ul=document.getElementsByTagName("li");

    var li=document.createElement('li');
        ul_box.appendChild(li);

    console.log(ul);
//HTMLCollection(5) [li, li, li, li, li]  getElementsByTagName可以动态添加
    </script>
</body>
</html>
  • 2.querySelectorAll:无映射机制
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>鼠标事件</title>
   </head>
<body> 
 <ul id=ul_box>
     <li>1</li>
     <li>2</li>
     <li>3</li>
     <li>4</li>
 </ul>
    <script>
    /* 获取元素的映射机制
     * querySelectorAll:无映射机制
     */

    var ul1=document.querySelectorAll('li');
    var li=document.createElement('li');
        ul_box.appendChild(li);
    console.log(ul1);
//HTMLCollection(4) [li, li, li, li] querySelectorAll动态添加后不起作用
    </script>
</body>
</html>
6.常用的事件行为
  • 1.【鼠标事件】
    • onclick:点击(移动端click被识别为单击)
  <!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>鼠标事件</title>
    <style>
      #box{
          width:200px;
          height:200px;
          background-color:pink;
      }
    </style>
</head>
<body>
    <div id="box"></div> 

    <script>
    var box=document.querySelector('#box'); 
    box.onclick=function(){
        console.log('单机')
    }    
    </script>
</body>
</html>
  • ondblclick:双击
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>鼠标事件</title>
    <style>
      #box{
          width:200px;
          height:200px;
          background-color:pink;
      }
    </style>
</head>
<body>
    <div id="box"></div> 

    <script>
    var box=document.querySelector('#box'); 
     box.ondblclick=function () {
         console.log('双击');
     }
    </script>
</body>
</html>
  • mousedown:鼠标按下
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>鼠标事件</title>
    <style>
      #box{
          width:200px;
          height:200px;
          background-color:pink;
      }
    </style>
</head>
<body>
    <div id="box"></div> 

    <script>
    var box=document.querySelector('#box'); 
      box.onmousedown =function () {
         console.log('鼠标按下');
     }    
    </script>
</body>
</html>
  • mouseup:鼠标抬起
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>鼠标事件</title>
    <style>
      #box{
          width:200px;
          height:200px;
          background-color:pink;
      }
    </style>
</head>
<body>
    <div id="box"></div> 

    <script>
    var box=document.querySelector('#box'); 
       box.onmouseup =function () {
         console.log('鼠标抬起');
     }  
    </script>
</body>
</html>
  • mouseover:鼠标滑过
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>鼠标事件</title>
    <style>
      #box{
          width:200px;
          height:200px;
          background-color:pink;
      }
    </style>
</head>
<body>
    <div id="box"></div> 

    <script>
    var box=document.querySelector('#box'); 
      box.onmouseover=function () {
         console.log('鼠标滑过');
     }
    </script>
</body>
</html>
  • mouseout:鼠标滑过
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>鼠标事件</title>
    <style>
      #box{
          width:200px;
          height:200px;
          background-color:pink;
      }
    </style>
</head>
<body>
    <div id="box"></div> 

    <script>
    var box=document.querySelector('#box'); 
         box.onmouseout=function () {
         console.log('鼠标滑出');
     }
    </script>
</body>
</html>
  • mouseenter:鼠标进入
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>鼠标事件</title>
    <style>
      #box{
          width:200px;
          height:200px;
          background-color:pink;
      }
    </style>
</head>
<body>
    <div id="box"></div> 

    <script>
    var box=document.querySelector('#box'); 
    box.onmouseenter=function () {
         console.log('鼠标移入');
     }
    </script>
</body>
</html>
  • mouseleave:鼠标离开
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>鼠标事件</title>
    <style>
      #box{
          width:200px;
          height:200px;
          background-color:pink;
      }
    </style>
</head>
<body>
    <div id="box"></div> 

    <script>
    var box=document.querySelector('#box'); 
      box.onmouseleave=function () {
         console.log('鼠标移出');
     }
    </script>
</body>
</html>
  • mousewheel:鼠标滚轮滚动
<!DOCTYPE html>
<html>
<head>
   <meta charset="UTF-8">
   <title>鼠标事件</title>
   <style>
     #box{
         width:200px;
         height:200px;
         background-color:pink;
     }
   </style>
</head>
<body>
   <div id="box"></div> 

   <script>
   var box=document.querySelector('#box'); 
      box.onmousewheel =function () {
        console.log('鼠标的滚轮事件');
    }
   </script>
</body>
</html>
  • contextmenu:鼠标右键点击
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>鼠标事件</title>
    <style>
      #box{
          width:200px;
          height:200px;
          background-color:pink;
      }
    </style>
</head>
<body>
    <div id="box"></div> 

    <script>
    var box=document.querySelector('#box'); 
        box.oncontextmenu =function () {
         console.log(' 鼠标右击');
     }
    </script>
</body>
</html>
  • 案例:单机和双击
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>鼠标事件</title>
    <style>
      #box{
          width:200px;
          height:200px;
          background-color:pink;
      }
    </style>
</head>
<body>
    <div id="box"></div> 

    <script>
    var box=document.querySelector('#box'); 
        box.onclick=function(){
        //鼠标点击第一次的时候先不着急执行单机函数 等一会 看是否点击了第二下
        // 若点击第二下,那就会自动执行双击:这是就要不执行单机对应的代码
        clearTimeout(this.timer);
        this.dbl=false;
       this.timer=setTimeout(()=>{
            if(this.dbl)return;
           console.log('单机');//=>单机的业务代码
        },300)      
    }
      box.ondblclick=function () {
          this.dbl=true;
         console.log('双击');
     }
    
    </script>
</body>
</html>
  • 2.【键盘事件】

绑定键盘事件的:input textarea window document.body;

  • keydown 按下某个键
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>键盘事件</title>
     <style>
      #box{
          width:200px;
          height:200px;
          background-color:pink;
      }
    </style>
</head>
<body>

   <div id="box" contenteditable='true'></div>
 
    <script>
   var box=document.getElementById('box');   
    //方法一:
    // div元素行内添加 contenteditable='true' div是一个可编辑的框
      box.onkeydown=function(){
       console.log('onkeydown');
      }

   //方法二
     window.onkeydown=function(){
       console.log('window keydown');
      }
      
    </script>
</body>
</html>
  • keyup 抬起某个键
  • keypress 长按
  • 3.【移动端手指事件】
    • 单手指事件模型 Touch
    • ontouchstart 手指按下 手指碰到屏幕
<!DOCTYPE html>
<html>
<head>
   <meta charset="UTF-8">
   <title>事件</title> 
   <style>
     #box{
         width:200px;
         height:200px;
         background-color:pink;
     }
   </style>    
</head>
<body>
<div id="box" contenteditable='true'></div>
<script>
var box=document.getElementById('box');
    box.ontouchstart=function () {
     console.log('start')
 }
</script>
</body>
</html>
  • ontouchmove 手指移动 手指在屏幕上移动
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>事件</title> 
    <style>
      #box{
          width:200px;
          height:200px;
          background-color:pink;
      }
    </style>    
</head>
<body>
 <div id="box" contenteditable='true'></div>
<script>
 var box=document.getElementById('box');
   box.ontouchmove=function () {
      console.log('手指在屏幕上移动')
  }
</script>
</body>
</html>

  • ontouchend 手指松开 手指离开屏幕
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>事件</title> 
    <style>
      #box{
          width:200px;
          height:200px;
          background-color:pink;
      }
    </style>    
</head>
<body>
 <div id="box" contenteditable='true'></div>
<script>
 var box=document.getElementById('box');
    box.ontouchend=function () {
      console.log('手指离开屏幕')
  }
</script>
</body>
</html>
  • touchcancel 操作取消(一般应用于非正常状态下操作结束)
  • 4.【多手指事件模型Gesture】
    • gesturestart
    • gesturechange/gestureupdate
    • gestureend
    • gesturecancel
  • 5.【表单元素常用事件】
    • onfocus 获取焦点:光标进去input时 触发的事件
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>键盘事件</title>     
</head>
<body>
 <input type="text" id='inp'>
    <script>
  inp.onfocus=function(){
        console.log('聚焦');
    }  
    </script>
</body>
</html>
  • onblur 失去焦点:光标离开input时 触发的事件
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>键盘事件</title>     
</head>
<body>
 <input type="text" id='inp'>
<script>

  inp.onblur=function(){
        console.log('失焦');
    }
    
</script>
</body>
</html>
  • onchange 内容改变:内容改变时会触发,输入完成失焦后发生改变
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>键盘事件</title>     
</head>
<body>
 <input type="text" id='inp'>
    <script>
          inp.onchange=function(){
        console.log('内容改变时会触发');
    }
    </script>
</body>
</html>
  • oninput 监听键盘操作:内容改变时会触发该函数:输入时发生改变
<!DOCTYPE html>
<html>
<head>
   <meta charset="UTF-8">
   <title>键盘事件</title>     
</head>
<body>
<input type="text" id='inp'>
<script>

 inp.oninput=function(){
       console.log('内容改变触发函数');
   }
   
 </script>
</body>
</html>
  • 6.【音视频常用事件】
    • canplay:可以播放(资源没有加载完,播放中可能会卡顿)
    • canplaythrough:可以播放(资源已经加载完,播放中不会卡顿)
    • play 开始播放
    • playing 播放中
    • pause 暂停播放
  • 7.【其他常用事件】
    • load 资源加载完 window.onload img.onload
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>事件</title>     
</head>
<body>
<div class="box">我是页面资源</div>
<script>

    window.onload=function(){
       console.log('我是页面资源,我已加载完成');
   }
   
</script>
</body>
</html>
  • onresize :页面窗口大小发生改变的时候触发
 <!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>事件</title>     
</head>
<body>
<script>

    window.onresize=function () {
       console.log('页面窗口大小发生改变');
   }
   
</script>
</body>
</html>
  • unload 资源卸载
  • beforeunload 当前页面关闭之前
  • error 资源加载失败
  • scroll 滚动事件
  • readystatechange ajax请求状态改变事件
  • oncontextmenu:鼠标右键触发
  • transitionend
  • readystatechange
  • window.onload和jq的ready事件 有什么区别?
 $(document).ready(function () {
     //DOM 加载完成后触发
 })
 //可简写成
 $(function(){

 })();
7.事件对象
  • 1.event:事件对象,是浏览器默认传给这个函数的
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>事件对象</title>
  <style>
  #box{
      width:200px;
      height:200px;
      background-color:pink;
  }
</style>
</head>
<body>
  <div id="box">
      <button>按钮</button>
  </div>

  <script>
  let box=document.getElementById('box');   
  box.onclick=function(event){
      //兼容低版本浏览器
      event=event||window.event;

      //this是指绑定的元素
      console.log(this);//box

     //事件源  就是点击的哪个元素
      console.log(event.target);
      console.log(event);

     //点击的为止 距离可视窗口的左边距
      console.log(event.clientX);

      //点击的为止 距离可视窗口的上边距
      console.log(event.clientY);

      //点击的位置  距离body的上边距          
      console.log(event.pageX);

      // Arguments [MouseEvent, callee: ƒ, Symbol(Symbol.iterator): ƒ]
      console.log(arguments);
  }   
  </script>
</body>
</html>
  • 2.event.target.value : 获取input输入的具体值

高版本浏览器可以直接使用id当做变量

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>事件对象</title>
</head>
<body>
<input type="text" id='inp'>
<script>
inp.oninput=function () {
  console.log(this);//<input type="text" id='inp'>
  console.log(event.target);// <input type="text" id='inp'>
  console.log(event.target.value);//控制台显示具体的值
}
</script>
</body>
</html>
8.需求:当用户输入完成,敲回车键的时候alert用户输入的内容
  • 1.event.code方案
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>事件对象</title>
</head>
<body>      
<input type="text" id='inp'>

<script>
// + 1.event.code方案
inp.onkeydown=function(event){
    console.log(event);
    if(event.code.toLowerCase()=='enter'){
       alert('event.target.value');
    }     
}
</script>
</body>
</html>
  • 2.event.key方案
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>事件对象</title>
</head>
<body>      
<input type="text" id='inp'>

<script>
// + 2.event.key方案
inp.onkeydown=function(event){
    console.log(event);
    if(event.key.toLowerCase()=='enter'){
       alert('event.target.value');
    }
}
</script>
</body>
</html>
9.推盒子
<!DOCTYPE html>
<html >
<head>
  <meta charset="UTF-8">
  <title>推盒子</title>
  <style>
  *{
      margin:0;
      padding:0;
  }
  #box{
      width:100px;
      height:100px;
      background-color:pink; 
  }
  </style>
</head>
<body>
  <div id="box"></div>

  <script>
  //按键盘的上下左右键 控制盒子上下左右的移动
  let box=document.getElementById('box');
  box.top=0;
  box.left=0;
  window.onkeydown=function (event) {
     console.log(event);
     switch(event.code){
      //按的上键
      case 'ArrowUp':
      box.top-=10;
      // box.style.transform=`translate(${box.left}px,${box.top}px)`
      break;

      //按的下键
      case 'ArrowDown':
      box.top+=10;
      // box.style.transform=`translate(${box.left}px,${box.top}px)`
      break;

      //按的是左键
      case 'ArrowLeft':
      box.left-=10;
      // box.style.transform=`translate(${box.left}px,${box.top}px)`
      break;

      //按的是右键
      case 'ArrowRight':
      box.left+=10;

      break;    
     }
      box.style.transform=`translate(${box.left}px,${box.top}px)`
  }    
  </script>
</body>
</html>
10.阻止默认行为
  • 1.preventDefault:阻止默认行为 多数使用
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8"> 
  <title>阻止默认行为</title>
   <style>
   *{
      margin:0;
      padding:0;
  }
  #link{
      display:block;
      width:100px;
      height:100px;
      background-color:pink;
  }
  #box{
      width:100px;
      height:200px;
      background-color:blue;
      position:fixed;
      display:none;
  }
  </style>
</head>
<body>
  <a href="http://baidu.com" id='link'>百度一下</a>
  <div id="box"></div>
  <script>
   let link=document.querySelector('#link');
   link.onclick=function (event) {
       //1.preventDefault:阻止默认行为 多数使用
       event.preventDefault();//阻止默认行为 阻止标签本身只有的特性
       alert('我是弹出框');
   }
  </script>
</body>
</html>
  • 2.return false 不推荐
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8"> 
  <title>阻止默认行为</title>
   <style>
   *{
      margin:0;
      padding:0;
  }
  #link{
      display:block;
      width:100px;
      height:100px;
      background-color:pink;
  }
  #box{
      width:100px;
      height:200px;
      background-color:blue;
      position:fixed;
      display:none;
  }
  </style>
</head>
<body>
  <a href="http://baidu.com" id='link'>百度一下</a>
  <div id="box"></div>
  <script>
   let link=document.querySelector('#link');
   link.onclick=function (event) {
       alert('我是弹出框');

       //2.阻止默认行为,组件标签本身具有的特性
       return false;
   }
  </script>
</body>
</html>
  • 3.阻止页面右击弹出的框
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8"> 
  <title>阻止默认行为</title>
   <style>
   *{
      margin:0;
      padding:0;
  }
  #link{
      display:block;
      width:100px;
      height:100px;
      background-color:pink;
  }
  #box{
      width:100px;
      height:200px;
      background-color:blue;
      position:fixed;
      display:none;
  }
  </style>
</head>
<body>
  <a href="http://baidu.com" id='link'>百度一下</a>
  <div id="box"></div>
  <script>
   let link=document.querySelector('#link');
  //2.阻止页面右击弹出的框 
  link.oncontextmenu=function(){
       event.preventDefault();
       console.log('我是阻止页面右击弹出的框 ');
   }
  </script>
</body>
</html>
  • 4.右击展示小框框
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8"> 
  <title>阻止默认行为</title>
   <style>
   *{
      margin:0;
      padding:0;
  }
  #link{
      display:block;
      width:100px;
      height:100px;
      background-color:pink;
  }
  #box{
      width:100px;
      height:200px;
      background-color:blue;
      position:fixed;
      display:none;
  }
  </style>
</head>
<body>
  <a href="http://baidu.com" id='link'>百度一下</a>
  <div id="box"></div>
  <script>
   let link=document.querySelector('#link'); 
  //4.右击展示小框框
    window.oncontextmenu=function(event){
       event.preventDefault();
       //鼠标右击的为止距离可以从窗口偏移量
       console.log(event.clientX,event.clientY)
      box.style.display='block';
      box.style.left=event.clientX+'px';
      box.style.top=event.clientY+'px';
   }  
  </script>
</body>
</html>
11.input只能输入数字
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>input只能输入拼音上面数字</title>
</head>
<body>
  <input type="text" id='inp'>
<script>
 let inp=document.querySelector('#inp');
  inp.onkeydown=function(event){
    console.log(event);
    if((event.keyCode >= 48 && event.keyCode<=57)||event.keyCode==8){
        return true;
    }
    return false;
  }
</script>
</body>
</html>
12.事件的传播

事件的传播,点击穿透;触发了一个元素的某个事件,他会一次吧父节点 祖父节点...最外层的节点(body或者html)

  • 1.事件的传播机制:先传播 在处理 在冒泡
  • 2.捕获:找到点击的元素,从外层向里找
  • 3.处理:目标处理阶段找到点击的元素之后 处理以下事件对象
  • 4.冒泡:找到了点击元素,也处理好了事件对象,在一层一层的从里向外执行各个对应的事件
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>事件的传播</title>
  <style>
  #outer{
      width:400px;
      height:400px;
      background-color:blue;
      margin:30px auto;
  }
   #inner{
      width:200px;
      height:200px;
      background-color:red;
      margin:100px auto;
  }
   #center{
      width:100px;
      height:100px;
      background-color:green;
      margin:50px auto;
  }
  </style>
</head>
<body>
  <div id="outer">
      <div id="inner">
          <div id='center'></div>
      </div>
  </div>

  <script>   
  outer.onclick=function(){
      console.log('outer');//=>无论点击那个盒子都是输出outer
  }

   inner.onclick=function(){
      console.log('inner');
  //=>点击outer盒子,不会触发inner,点击inner盒子 及上面的盒子会触发inner
  }

   center.onclick=function(event){
      console.log(event);//只有点击center盒子的时候触发event
      console.log('center');//=>点击center盒子的时候触发的事件源是center
      event.stopPropagation();//阻止冒泡  阻止外传
      event.cancelBubble=true;//IE低版本
  }

  document.body.onclick=function(){
      console.log('body');
  //=>点击center盒子的时候不会触发body,因为做了event.stopPropagation();
  //阻止冒泡  阻止外传,点击其他盒子的时候都会触发body
  }
  </script>  
</body>
</html>
  • 5.onmouseenter 不具备冒泡的特性
  • 6.onmouseover 具备 冒泡的特征
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>事件的传播</title>
  <style>
  #outer{
      width:400px;
      height:400px;
      background-color:blue;
      margin:30px auto;
  }
   #inner{
      width:200px;
      height:200px;
      background-color:red;
      margin:100px auto;
  }
   #center{
      width:100px;
      height:100px;
      background-color:green;
      margin:50px auto;
  }
  </style>
</head>
<body>
  <div id="outer">
      <div id="inner">
          <div id='center'></div>
      </div>
  </div>

<script>
// 当鼠标从outer划入inner之后:肯定会触发inner的enter和over事件,
//但是我们发现, outer之后over事件执行了,enter事件没有执行。
//这说明了 enter事件没有穿透;over事件穿透了inner的over触发传递给了outer
    outer.onmouseenter=function(){
    console.log('enter')
  }
  outer.onmouseover=function(){
    console.log('over')
  }
</script>
</body>
</html>
13.事件的委托
  • 1.js循环的方式
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>事件的委托</title>
  <style>
  li{
      height:50px;
      border:1px solid #ccc;
      margin:10px;
  }
  </style>
</head>
<body>
输入 ul>li*100{$}  出现提示回车
  <script>
  //1.js循环
  let lis=document.querySelectorAll('li');
  for(let i=0;i<lis.length;i++){
      lis[i].onclick=function(event){
          console.log(event.target);//点击页面中的每个li,控制台就会显现那个li
      }
  }   
  </script>
</body>
</html>
  • 2.事件委托
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>事件的委托</title>
  <style>
  li{
      height:50px;
      border:1px solid #ccc;
      margin:10px;
  }
  </style>
</head>
<body>
输入 ul>li*100{$}  出现提示回车
  <script>
//2.事件委托
  //本来是要绑定给每一个子元素的事件,我们可以绑定到父元素上
  // 通过事件的冒泡结合 e.target 我们实现要的效果,避免了给每一个元素的绑定事件
  let ul=document.querySelector('li');
  ul.onclick=function(event){
      //点击每一个li的时候都会触发ul的点击事件 因为事件的冒泡机制;
      console.log(event.target)
  }  
  </script>
</body>
14.多级菜单
  • 1.JQ版
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>多级菜单</title>
<style>
  .hide{
    display: none;
  }
</style>
</head>
<body>
<!-- 
给 ul  绑定点击事件; 通过事件委托的方式 查出点击元素,然后控制点击元素的兄弟元素 
加不加hide类名即可
 -->
<ul id='box'>
  <li>
    <span>一级菜单1</span>
    <ul>
      <li>
        <span>二级菜单1</span>
        <ul>
          <li>
            <span>三级菜单1</span>
          </li>
          <li>
            <span>三级菜单2</span>
            <ul>
              <li>
                <span>四级菜单1</span>
              </li>
            </ul>
          </li>
        </ul>
      </li>
      <li>
        <span>二级菜单2</span>
        <ul>
          <li>
            <span>三级菜单1</span>
          </li>
          <li>
            <span>三级菜单2</span>
          </li>
        </ul>
      </li>
    </ul>
  </li>
  <li>
    <span>一级菜单2</span>
    <ul>
      <li>
        <span>二级菜单1</span>
        <ul>
          <li>
            <span>三级菜单1</span>
          </li>
          <li>
            <span>三级菜单2</span>
            <ul>
              <li>
                <span>四级菜单1</span>
              </li>
            </ul>
          </li>
        </ul>
      </li>
      <li>
        <span>二级菜单2</span>
        <ul>
          <li>
            <span>三级菜单1</span>
          </li>
          <li>
            <span>三级菜单2</span>
          </li>
        </ul>
      </li>
    </ul>
  </li>
  <li>
    <span>一级菜单3</span>
    <ul>
      <li>
        <span>二级菜单1</span>
        <ul>
          <li>
            <span>三级菜单1</span>
          </li>
          <li>
            <span>三级菜单2</span>
            <ul>
              <li>
                <span>四级菜单1</span>
              </li>
            </ul>
          </li>
        </ul>
      </li>
      <li>
        <span>二级菜单2</span>
        <ul>
          <li>
            <span>三级菜单1</span>
          </li>
          <li>
            <span>三级菜单2</span>
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>
</body>
</html>
<!-- 1.JQ版 -->
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>

<script>
$("#box").on('click',function(e){
  var $tar = $(e.target);
  if($tar[0].nodeName.toLowerCase() === 'span'){
    let $next = $tar.siblings('ul');
    $next.toggleClass('hide');
    if($next.hasClass('hide')){
      $next.find('ul').addClass('hide');
      // $next.children('ul');
      // find 是所有后代  children是获取子代
    }
  }
});
</script>
  • 2.js版
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
  .hide{
    display: none;
  }
</style>
</head>
<body>
<!-- 
给 ul  绑定点击事件; 通过事件委托的方式 查出点击元素,然后控制点击元素的兄弟元素
加不加hide类名即可
-->
<ul id='box'>
  <li>
    <span>一级菜单1</span>
    <ul>
      <li>
        <span>二级菜单1</span>
        <ul>
          <li>
            <span>三级菜单1</span>
          </li>
          <li>
            <span>三级菜单2</span>
            <ul>
              <li>
                <span>四级菜单1</span>
              </li>
            </ul>
          </li>
        </ul>
      </li>
      <li>
        <span>二级菜单2</span>
        <ul>
          <li>
            <span>三级菜单1</span>
          </li>
          <li>
            <span>三级菜单2</span>
          </li>
        </ul>
      </li>
    </ul>
  </li>
  <li>
    <span>一级菜单2</span>
    <ul>
      <li>
        <span>二级菜单1</span>
        <ul>
          <li>
            <span>三级菜单1</span>
          </li>
          <li>
            <span>三级菜单2</span>
            <ul>
              <li>
                <span>四级菜单1</span>
              </li>
            </ul>
          </li>
        </ul>
      </li>
      <li>
        <span>二级菜单2</span>
        <ul>
          <li>
            <span>三级菜单1</span>
          </li>
          <li>
            <span>三级菜单2</span>
          </li>
        </ul>
      </li>
    </ul>
  </li>
  <li>
    <span>一级菜单3</span>
    <ul>
      <li>
        <span>二级菜单1</span>
        <ul>
          <li>
            <span>三级菜单1</span>
          </li>
          <li>
            <span>三级菜单2</span>
            <ul>
              <li>
                <span>四级菜单1</span>
              </li>
            </ul>
          </li>
        </ul>
      </li>
      <li>
        <span>二级菜单2</span>
        <ul>
          <li>
            <span>三级菜单1</span>
          </li>
          <li>
            <span>三级菜单2</span>
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>
</body>
</html>
<script>
/* 
box.classList
add(类名)  新增类名
remove(类名) 删除类名
toggle(类名)  切换类名 有这个类名就删除 没有这个类名就添加
contains(类名)  查看是否包含这个类名; 包含 就是true 不包含就是false

*/
let box = document.querySelector('#box');

box.onclick = function(e){
  e = e || window.event;
     let tar = e.target || e.srcElement;// 容错机制

  if(tar.nodeName.toLowerCase() == 'span'){
    // 证明点击的是 span
    let next = tar.nextElementSibling;// 获取点击元素的弟弟元素节点

    // 判断弟弟元素节点是否存在, 存在的话 在判断是否是ul
    if(next && next.nodeName.toLowerCase() == 'ul'){

      next.classList.toggle('hide');
// 当 这个 ul被遮住之后 要让所有的后代都遮住
// 就是 判断 这个ul 有没有 hide; 有hide 就让所有的后代 ul 都加上hide

      if(next.classList.contains('hide')){
        let uls = next.getElementsByTagName('ul');
        for(let i = 0; i < uls.length; i++){
          uls[i].classList.add('hide')
        }
      }
    }
  }
}
</script>
15.鼠标跟随显示图片
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>鼠标跟随显示图片</title>
<style>  
  .lit_imgbox{
    width: 200px;
    height: 200px;
    overflow: hidden;
    margin: 20px;
  }
  .lit_imgbox img{
    width: 100%;
    height: 100%;
  }
  #big_imgbox{
    display: none;
    width: 400px;
    height: 400px;
    position: fixed;
    left: 0;
    top: 0;
  }
  #big_imgbox img{
    width: 100%;
    height: 100%;
  }
</style>
</head>
<body>
<!--  
  $.extend({}) // 扩展到JQ自己身上  $.
  $.fn.extend({}) // 扩展到JQ的原型上  $().
  $.extend = $.fn.extend = function(){}
-->

<div class="lit_imgbox">
  <img src="https://dss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=28057649,500045150&fm=26&gp=0.jpg" alt="">
</div>
<div class="lit_imgbox">
  <img src="https://dss0.bdstatic.com/-0U0bnSm1A5BphGlnYG/tam-ogel/0176cb5938268a444a09a472232a3ee9_259_194.jpg" alt="">
</div>
<div class="lit_imgbox">
  <img src="https://dss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=184164756,4275686560&fm=173&app=49&f=JPEG?w=312&h=208&s=D5A5FC5852F3B06F1A085B1D0300C0C4" alt="">
</div>
<div class="lit_imgbox">
  <img src="https://dss0.baidu.com/6ONWsjip0QIZ8tyhnq/it/u=3124272852,4033309804&fm=173&app=49&f=JPEG?w=312&h=208&s=F9A01B7004BA5396820051E90300A020" alt="">
</div>
<div id="big_imgbox">
  <img src="https://dknet.gitee.io/daily_work/%E6%9D%8E%E6%99%93%E5%A8%9F/images/%E4%B8%8B%E8%BD%BD.jfif" alt="">
</div>
</body>
</html><script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>

<!-- 1.JQ版 -->
<script>
let $lit = $('.lit_imgbox'),
    $big = $('#big_imgbox');
  $lit.on('mouseenter',function(){
    $big.show();
    // 当划过小图的时候  要获取到小图的图片地址
    this.img = $(this).find('img').attr('src');
    console.log(this.img)
    // 获取到小图的地址之后 再赋给 大图
    $big.find('img').attr('src',this.img)
  })    
  $lit.on('mousemove',function(e){
    $big.css({
      transform:`translate(${e.clientX+5}px,${e.clientY+5}px)`
    })
  })   
  $lit.on('mouseleave',function(){
    $big.hide()
  })   
</script>
16.DOM2级事件
  • 1.onclick
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>DOM2级事件</title>
  <style>
    #box{
        width:100px;
        height:100px;
        background-color:pink;
    }

      #outer{
      width:400px;
      height:400px;
      background-color:blue;
      margin:30px auto;
  }
   #inner{
      width:200px;
      height:200px;
      background-color:red;
      margin:100px auto;
  }
   #center{
      width:100px;
      height:100px;
      background-color:green;
      margin:50px auto;
  }
  </style>
</head>
<body>
  <div id="box"></div>
<script>
  let box=document.querySelector('#box');
  //1.onclick
   box.onclick=function(){
      console.log('我是第一次输入内容');//点击盒子控制台提示
   };
</script>  
  </body>
</html>
  • 2.添加事件:元素.addEventListener(事件类型,回调函数,布尔类型(可省略))
    • 1.同一个事件类型 可以绑定多个回调函数
    • 2.第三个参数 bol默认是false;false代表函数要在冒泡阶段执行;true代表函数要在捕获阶段执行
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>DOM2级事件</title>
  <style>
    #box{
        width:100px;
        height:100px;
        background-color:pink;
    }

  </style>
</head>
<body>
  <div id="box"></div>
<script>

   let fn=function(){
   console.log('我是第二次输出内容')
  }

  box.addEventListener("click",fn);

   box.addEventListener("click",function(){
   console.log('我是第三次输出内容')
  });

</script>
</body>
</html>
  • 3.移除事件:元素.removeEventListener(事件类型,回调函数,bol(可省略))
    • 移除事件是 要保证移除的哪个事件对应函数地址是存在的,不是一个新地址
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>DOM2级事件</title>
  <style>
    #box{
        width:100px;
        height:100px;
        background-color:pink;
    }
  </style>
</head>
<body>
  <div id="box"></div>
<script>
   let fn=function(){
   console.log('我是第二次输出内容')
  }
   box.addEventListener("click",fn);

   box.addEventListener("click",function(){
   console.log('我是第三次输出内容')
  });
   box.removeEventListener("click",fn);
</script>
  </body>
</html>
  • 3.DOM2级语法
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>DOM2级事件</title>
  <style>  
      #outer{
      width:400px;
      height:400px;
      background-color:blue;
      margin:30px auto;
  }
   #inner{
      width:200px;
      height:200px;
      background-color:red;
      margin:100px auto;
  }
   #center{
      width:100px;
      height:100px;
      background-color:green;
      margin:50px auto;
  }
  </style>
</head>
<body>  
  <div id="outer">
      <div id="inner">
          <div id='center'></div>
      </div>
  </div>
<script>     
   outer.addEventListener('click',function(){
      console.log('outer');//点击outer 触发outer盒子
   },true);
  inner.addEventListener('click',function(){
      console.log('inner');//点击inner  触发inner和子和下面的outer盒子
   },true);
  center.addEventListener('click',function(){
      console.log('center');//点击center 触发center盒子本身和outer和inner
   },true);
</script>
  </body>
</html>
  • 4.JQ的事件绑定 利用的是DOM2级事件绑定
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>DOM2级事件</title>
  <style>  
  #box{
        width:100px;
        height:100px;
        background-color:pink;
    }
  </style>
</head>
<body>  
   <div id="box"></div>
  <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>

<script>
  // 3.JQ的事件绑定 利用的是DOM2级事件绑定
  let $box=$('#box');
  $box.on('click',function(){
          console.log('我是jq1,我是默认二级事件绑定')
      });

  let fn=function(){
          console.log('我是jq2,我是默认二级事件绑定')
      };

  $box.on('click',fn);//绑定    
  $box.off('click',fn);//解除

</script>
</body>
</html>
17 放大镜
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
     <title>放大镜</title>
<style>
*{
  margin:0;
  padding:0;
}
     #mag{
         margin:0px auto;
     }
     .minBox{
         width:200px;
         height:200px;
         border:1px solid #ccc;
     }
     .minBox .mask{
         position:absolute;
         left:8px;
         top:20px;
         cursor: move;
         width:100px;
         height:100px;
         background:rgba(0,0,0,0.5);
     }
     .minBox img{
          width:100%;
          height:100%;
     }
     .bigBox{
         width:300px;
         height:300px;
         border:1px solid #ccc;
         position:relative;
         left:201px;
         top:-200px;
         overflow: hidden;
         display:none;
     }
    .bigBox img{
        width:600px;
        height:600px;
        position: absolute;
    }
</style>
</head>
<body>
  <div id="mag">
      <div class="minBox">
          <div class='mask'></div>
          <img src="https://img11.360buyimg.com/n1/s450x450_jfs/t1/101657/4/19179/137400/5e9ade96E47d86e71/0cf6e05c9b7d4360.jpg" alt="">
      </div>

      <div class="bigBox">
          <img src="https://img14.360buyimg.com/n0/jfs/t1/101657/4/19179/137400/5e9ade96E47d86e71/0cf6e05c9b7d4360.jpg" alt="">
      </div>
  </div>

<script>
  //宽度比:     蒙层/小图=大盒子/大图片  100/200=300
let min=document.querySelector('.minBox');  
let mask=document.querySelector('.mask');    
let big=document.querySelector('.bigBox');     
let bigImg=big.querySelector('img');
min.onmouseenter=function(){
    //1.滑入小盒子的时候,要让 蒙层和大盒子显示出来
    mask.style.display='block';
    big.style.display='block';
}
min.onmouseleave=function(){
    //2.离开小盒子 要让蒙层和小盒子隐藏
    mask.style.display='none';
    big.style.display='none';
}

//鼠标在小盒子上移动时,要让蒙层随着移动
min.onmousemove=function(event){
 //由于 蒙层时相对于小盒子  进行移动的
 //想实现蒙层跟着鼠标移动 需要算出 鼠标 距离 小盒子的偏移量
 //把这个偏移量设置给 蒙层  就正好时蒙层在盒子上的位置
 //偏移量:用鼠标到body的偏移-盒子到body的偏移
 //偏移量:用鼠标到可是窗口的偏移-盒子到可视窗口的 偏移
 console.log(event.pageX,event.clientX);
 let curO=offset(this);//算出this(min)小盒子到body偏移量
 let left=event.pageX-curO.left-mask.clientWidth/2,
     top=event.pageY-curO.top-mask.clientHeight/2;//left top分别对应蒙层在小盒子中的偏移量

  // 考虑边界问题?
  // 向左走 最多走到0 不能是负数;向右走 最多到 小盒子款-蒙层宽;
  // 向上 最多走到0 不能为负数;向下最多到 小盒子高 -蒙层高
   let maxLeft=this.clientWidth-mask.clientWidth,
       maxTop=this.clientHeight-mask.clientHeight;//右下边界就算出来了;

      // left 的左边界是0; 右边界是maxL
      // top 的上边界是0; 下边界是maxT
      // 超出边界  做什么?
      // 超出边界  就让对应的值 等于边界即可
     left=left<0?0:(left>maxLeft?maxLeft:left);
     if(top<0){
        top=0
     }else if(top>maxTop){
        top=maxTop
     }else{
         top=top;
     }

     mask.style.left=left+"px";
     mask.style.top=top+"px";

   let n=big.clientHeight/mask.clientHeight;
   bigImg.style.left=-left*3+'px';
   bigImg.style.top=-top*3+'px';

}

function offset(element){
    //可以获取到element这个元素到body的偏移量
  let left=element.offsetLeft,
      top=element.offsetTop;//获取当前元素到父级参照物的偏移量
  let parent=element.offsetParent;//获取父级参照物

  while(parent){
     // 若父级参照物存在
  left+=(parent.clientLeft||0)+parent.offsetLeft;
  top+=(parent.clientTop||0)+parent.offsetTop;
  parent=parent.offsetParent;
  }
  return{
      left,
      top
  }
}
</script>

<script>
new mag('#mag');
new mag('#mag2');
new mag('#mag3');
</script>
</body>
</html>
18.事件委托应用
  • 1.增加删除新闻 jq实现 非事件委托
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>事件委托的应用场景</title>
  <link rel="stylesheet" href="reset.min.css">
  <style>
  .box{
      font-size:16px;
      margin:20px;
  }
  .newsList{
      margin-bottom:10px;
  }
  .newsList li{
      line-height:30px;
      border-bottom:1px solid #ccc;
  }
  </style>
</head>
<body>
  <div class="box">
      <ul class="newsList">
          <li>我是新闻1
              <a href="javascript:;">删除</a>
          </li>
            <li>我是新闻2
              <a href="javascript:;">删除</a>
          </li>
            <li>我是新闻3
              <a href="javascript:;">删除</a>
          </li>
            <li>我是新闻4
              <a href="javascript:;">删除</a>
          </li>
            <li>我是新闻5
              <a href="javascript:;">删除</a>
          </li>

      </ul>
      <a href="javascript:;" id='addNews'>新增</a>
  </div>

<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>

<!-- 1.jq实现 非事件委托-->
<script>
    let $addNews=$('#addNews'),
        $newsList=$('.newsList'),
        $links=$newsList.find('a');
        count=5;

        //只给默认的五个A点击事件行为绑定方法
        $links.click(function(){
          //this:当前点击的删除的按钮A
          $(this).parent().remove();
        })

        $addNews.click(function(){
            let str=``;
            for(let i=0;i<5;i++){
                str+=`<li>我是新闻${++count}
              <a href="javascript:;">删除</a>
          </li>`;
            }
            $newsList.append(str);
            //新增的删除按钮,没有绑定点击事件,需要在每一次新增完成,重新获取到所有的a,给其点击事件行为绑定方法
             $links=$newsList.find('a');
             $links.click(function(){
          //this:当前点击的删除的按钮A
          $(this).parent().remove();
        })
        })
</script>
</body>
</html>
  • 2.jq 事件委托
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>事件委托的应用场景</title>
  <link rel="stylesheet" href="reset.min.css">
  <style>
  .box{
      font-size:16px;
      margin:20px;
  }
  .newsList{
      margin-bottom:10px;
  }
  .newsList li{
      line-height:30px;
      border-bottom:1px solid #ccc;
  }
  </style>
</head>
<body>
  <div class="box">
      <ul class="newsList">
          <li>我是新闻1
              <a href="javascript:;">删除</a>
          </li>
            <li>我是新闻2
              <a href="javascript:;">删除</a>
          </li>
            <li>我是新闻3
              <a href="javascript:;">删除</a>
          </li>
            <li>我是新闻4
              <a href="javascript:;">删除</a>
          </li>
            <li>我是新闻5
              <a href="javascript:;">删除</a>
          </li>

      </ul>
      <a href="javascript:;" id='addNews'>新增</a>
  </div>

<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>

<!-- 2.事件委托实现 -->
<script>
//给动态绑定渲染的元素的每个事件行为绑定方法=>事件委托
  let $addNews=$('#addNews'),
      $newsList=$('.newsList');
       count=5;

  $newsList.click(function (event) {
     let target=event.target,
         $target=$(target);
      if(target.tagName==='A'){
          $target.parent().remove();

      } 
  });

  $addNews.click(function(){
      let str=``;
      for(let i=0;i<5;i++){
          str+=`<li>我是新闻${++count}
      <a href="javascript:;">删除</a>
      </li>`;
      }
       $newsList.append(str);
  })
</script>
</body>
</html>
  • 3.购物车的css实现
<!DOCTYPE html>
<html >
<head>
  <meta charset="UTF-8">
  <title>事件委托应用场景2</title>
  <link rel="stylesheet" href="reset.min.css">
  <style>
  .shopBox{
      position:relative;
      box-sizing:border-box;
      display:block;
      width:100px;
      height:35px;
      line-height:35px;
      text-align:35px;
      background:pink;
      color:#000;
  }
  .shopBox .detail{
      display:none;
      position:absolute;
      top:35px;
      left:0;
      width:300px;
      height:100px;
      text-align:center;
      background:blue;
  }
  .shopBox:hover .detail{
      display:block;
  }
  </style>
</head>
<body>
<!-- //不基于js实现鼠标滑过展示详情,鼠标在按钮和详情区'展示详情',
//只要离开这两个区域,详情区域就'隐藏'
  //+ 1.详情区域必须要是当前盒子的后代元素
  // + 2.基于css3中的:hover即可实现 -->
  <a href="javascript:;" class='shopBox'>
  购物车
  <div class='detail'>暂无购物车信息</div>
 </a>

</body>
</html>
  • 4.购物车的事件委托实现
<!DOCTYPE html>
<html >
<head>
  <meta charset="UTF-8">
  <title>事件委托应用场景2</title>
  <link rel="stylesheet" href="reset.min.css">
  <style>
  html,body{
      min-height:100%;
      background:#f6f7fb;
  }
  .shopBox{
      position:relative;
      box-sizing:border-box;
      display:block;
      width:100px;
      height:35px;
      line-height:35px;
      text-align:35px;
      background:pink;
      color:#000;
  }
.detail{
      display:none;
      width:300px;
      height:100px;
      text-align:center;
      background:blue;
  }

  </style>
</head>
<body>
  <a href="javascript:;" class='shopBox'>
  购物车    
 </a>
<div class='detail'>暂无购物车信息</div>

<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>

<!-- 事件委托 -->
<script>
  let $detail=$('.detail');
  $(document).click(function(ev){
  let target=ev.target,
  $target=$(target);
  if($target.hasClass('shopBox')){
  $detail.slideToggle(300);
  return;
  }    
  $detail.slideUp(300); 
  });
  $detail.click(function(ev){
 //点击detail的时候,我们阻止冒泡传播也就不会在把上面的方法执行了
   ev.stopPropagation();
  })

</script>
</body>
</html>
  • 5.购物车 非事件委托
<!DOCTYPE html>
<html >
<head>
  <meta charset="UTF-8">
  <title>事件委托应用场景2</title>
  <link rel="stylesheet" href="reset.min.css">
  <style>
  html,body{
      min-height:100%;
      background:#f6f7fb;
  }
  .shopBox{
      position:relative;
      box-sizing:border-box;
      display:block;
      width:100px;
      height:35px;
      line-height:35px;
      text-align:35px;
      background:pink;
      color:#000;
  }
.detail{
      display:none;
      width:300px;
      height:100px;
      text-align:center;
      background:blue;
  }

  </style>
</head>
<body>
  <a href="javascript:;" class='shopBox'>
  购物车    
 </a>
<div class='detail'>暂无购物车信息</div>

<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>

<!-- 非事件委托:方法一 -->
<script>
  //点击购物车,按照详情区域现在的状态控制显示隐藏,
  //点击详情区域中的信息,不做任何的处理(也就是不隐藏),
  //但是点击除这两个区域以外的"任何区域",都让详情消失=>这种除啥啥事的事件源以外的其他事件源,
  //操作的时候统一做什么事情的时候,基本上都要用事件委托来解决
  let $detail=$('.detail');
  $(document).click(function(ev){
      let target=ev.target,
      $target=$(target);
      if($target.hasClass('shopBox')){
      //点击的是购物车按钮;toggle/slideToggle是jq自带的方法,
      //可以控制元素显示隐藏的切换,对应的是show/hide(slideDown/slideUp)
      $detail.slideToggle(300);
      return;
      }
      if($target.hasClass('detail')){
          //爱你寄的是detail则啥都不处理
          return;
      }
      //以上条件不成立,则让detail小时
      $detail.slideUp(300);
  })
</script>

</body>
</html>