事件类型与节点的操作

320 阅读6分钟

事件

什么是事件? 事件是在编程时系统内发生的动作或者发生的事情

比如用户在网页上单击一个按钮

什么是事件监听?

就是让程序检测是否有事件产生,一旦有事件触发,就立即调用一个函数做出响应,也称为 注册事件 语法:

注册事件

btn1.addEventListener("事件类型", 处理函数)

事件监听三要素:

事件源: 那个dom元素被事件触发了,要获取dom元素

事件: 用什么方式触发,比如鼠标单击 click、鼠标经过 mouseover 等 事件调用的函数: 要做什么事**

事件监听

1649081288008

演示 鼠标单击与鼠标移入

    <button class="btn1">开始</button>
    <button class="btn2">退出</button>
    <div></div>

    <script>
        /* 
        触发事件dom元素  事件类型   事件触发了 做业务  函数
         */
        let btn1 = document.querySelector(".btn1")
        // 注册事件 语法 : btn1.addEventListener("事件类型", 处理函数)

        // click 表示鼠标单击
        btn1.addEventListener("click", function(){
            console.log("开始抽奖");
        })
        let btn2 = document.querySelector(".btn2")
        btn2.addEventListener("click", function(){
            console.log("退出抽奖");
        })
        let div = document.querySelector("div")
        // mouseover 表示 鼠标移入到该区域内
        div.addEventListener("mouseover", function(){
            console.log("来呀 快活呀");
        })
    </script>

演示-- 点击数字减少

    <button class="btn1">1000</button>
    <div></div>
    <script>
        let btn1 = document.querySelector(".btn1")
        let times = 1000
        btn1.addEventListener("click", function(){
            btn1.value = times
            times--
            console.log(times);
        })
        // 方式二
        // 获取元素
        let button = document.querySelector('button')
        // 注册绑定点击事件
        button.addEventListener('click', function(){
            // 1、获取一下 按钮中的文本
            // console.log(button.innerText);

            // let num = button.innerText // 数据类型是字符串 比较注意做 + 运算
            // console.log(num + 1); // 字符串拼接
            // console.log(num - 1); // 隐式转换 转成数字

            // button.innerText = button.innerText - 1 // 不用担心变成字符串
            // button.innerText = button.innerText + 1 //  + 变成字符串

            // num = num - 1  // num -= 1  // --num
            // button.innerText -= 1
            --button.innerText
        })
    </script>

演示 点击隐藏

    <style>
        div{
            margin: 100px auto;
            width: 200px;
            height: 200px;
            background-color: aqua;
        }
    </style>
</head>
<body>
    <div></div>
    <script>
        // 点击div 隐藏 
        let div = document.querySelector('div')
        div.addEventListener('click', function(){
            div.style.display='none' // 点击 div 隐藏
        })
    </script>

案例 点击事件---随机点名

   <h1></h1>
    <button class="btn1">开始随机点名</button>
    <button class="btn2">停止点名</button>
    <script>
        let userName = ['赵云', '诸葛流云', '马云', '小云', '韩菱纱',' 云天舒', '玄霄', '慕容紫英', '紫胤真人']
        let h1 = document.querySelector('h1')
        let btn1 = document.querySelector('.btn1')
        let btn2 = document.querySelector('.btn2')
        let timeId
        // 方式一
        // btn1.addEventListener("click", function(){
        //     btn1.disabled=true
        //     timeId = setInterval(function(){
        //         let index = Math.round(Math.random() * (userName.length - 1))
        //         h1.innerText = userName[index]
                
        //     }, 50)
        // })
        // btn2.addEventListener("click", function(){
        //     clearInterval(timeId)
        //     btn1.disabled=false
        // })

        // 方式二
        function intervalDo(){
            let index = Math.round(Math.random() * (userName.length - 1))
            h1.innerText = userName[index]
        }    
        btn1.addEventListener("click", function(){
            if (timeId !== undefined){
                clearInterval(timeId)
            }
            timeId = setInterval(intervalDo, 100)
        })
        
        btn2.addEventListener('click', function () {
        // 重新启用 开始按钮
        // btn1.disabled = false;
        clearInterval(timeId);
      });
    </script>

事件监听版本

DOM L0

 事件源.on事件 = function() { }

DOM L2

 事件源.addEventListener(事件, 事件处理函数)

发展史:

DOM L0 :是 DOM 的发展的第一个版本; L:level

DOM L1:DOM级别1 于1998年10月1日成为W3C推荐标准

DOM L2:使用addEventListener注册事件

DOM L3: DOM3级事件模块在DOM2级事件的基础上重新定义了这些事件,也添加了一些新事件类型

演示 (了解

    <!-- 以下两种方式都不推荐 了解即可-->
    <!-- <button onclick="console.log(123)" >点击</button> -->
    <!-- <button onclick="show()">点击</button> -->

    <button class="btn1">点击</button>
    <button class="btn2">点击</button>
    <script>
      // 1 获取dom元素
      let btn1 = document.querySelector('.btn1');
      let btn2 = document.querySelector('.btn2');

      // 使用旧方式 L0 第一个版本的方式绑定点击事件  on+事件类型 = 匿名函数
      // on也可以是在 行内 绝对不推荐
      btn1.onclick = function () {
        console.log('事件触发啦');
      };
      btn1.onclick = function () {
        console.log('事件触发啦');
      };
      btn1.onclick = function () {
        console.log('事件触发啦');
      };

      // addEventListener 对一个事件类型 绑定多个处理函数 
      // on+事件 对一个事件类型 只能绑定一个处理函数

      btn1.onclick = show1;
      function show1() {
        console.log('show1');
      }

      btn2.addEventListener("click",function () {
        console.log("show");
      });
      btn2.addEventListener("click",function () {
        console.log("show");
      });
      btn2.addEventListener("click",function () {
        console.log("show");
      });
      btn2.addEventListener("click",function () {
        console.log("show");
      });
    </script>

事件类型

1649082943232

1649774346368

各类效果演示

    <style>
        * {
          margin: 0;
          padding: 0;
          box-sizing: border-box;
        }
        div {
          width: 200px;
          height: 200px;
          background-color: aqua;
        }
      </style>
</head>
<body>
    <div></div>

    <!-- 只有表单 元素 有获得焦点 失去焦点事件 -->
    <input type="text" />
    <script>
        
       //  mousemove  鼠标移动事件
        
        
      // 获取div元素
      let div = document.querySelector('div');
      let input = document.querySelector('input');

      // 绑定不同的事件
      div.addEventListener("click",function () {
        console.log("click 鼠标点击事件");
      })

      // 鼠标经过元素
      div.addEventListener("mouseenter",function () {
      console.log("mouseenter 鼠标经过");
      })

      // 鼠标离开元素
      div.addEventListener("mouseleave",function () {
      console.log("mouseleave 鼠标离开");
      })

      // 鼠标经过
    //   div.addEventListener("mouseover",function () {
    //     console.log("mouseover 鼠标经过");
    //   })

      // 鼠标离开
    //   div.addEventListener("mouseout",function () {
    //     console.log("mouseout 离开");
    //   })

      // 获得焦点
      input.addEventListener("focus",function () {
        console.log("输入框 获得焦点 ");
        document.body.style.backgroundColor='#000'
      })

      // // 失去焦点 
      input.addEventListener("blur",function () {
        console.log("输入框 失去焦点");
        document.body.style.backgroundColor='#fff'
      })

      // 键盘按下事件 div不行 表单可以 
      // 给body标签添加比较多
      document.body.addEventListener("keydown",function () {
        console.log("keydown 按下");
      })

      // 键盘抬起
      document.body.addEventListener("keyup",function () {
        console.log("keyup 抬起");
      })
      
      // 输入事件 输入框
      input.addEventListener("input",function () {
        console.log("只要你在我的输入框输入了内容,我就触发");
      })
    </script>

取消绑定点击事件

    <button>点击输出时间</button>
    <script>
        const btn = document.querySelector('button')
        function func(){
            console.log('一巴掌拍死你');
        }
        function func1(){
            console.log('一巴掌拍死你,那多拍几下');
        }
        // 绑定事件 addEventListener可以绑定多个同名事件
        btn.addEventListener('click', func)
        btn.addEventListener('click', func1)

        // 取消绑定 延时绑定
        setTimeout(function(){
            // 取消这个事件的绑定
            // removeEventListener 但无法取消匿名的函数 因为没有名称 不知道取消谁
            btn.removeEventListener('click',func)
        }, 5000)
    </script>

断点调试补充

1649643464099

高阶函数

掌握高阶函数用法,实现函数更多使用形式

高阶函数可以被简单理解为函数的高级应用,JavaScript 中函数可以被当成【值】来对待,基于这个特性实现函数的高级应用。

【值】就是 JavaScript 中的数据,如数值、字符串、布尔、对象等。

函数表达式 回调函数

1、函数表达式

函数表达式和普通函数并无本质上的区别:

1649164692670

普通函数的声明与调用无顺序限制,推荐做法先声明再调用

函数表达式必须要先声明再调用

    <button>按钮</button>
    <script>
      /* 
      高阶函数的应用 在react阶段大量的应用 

      高阶函数
      把一个函数 看成是个普通数据,应用在 参数 或者返回值  技术  
       */

      //  function f1(callback) {
      //    callback();
      //  }

      //  function f2() {
      //    console.log("我就是高阶函数");
      //  }

      //  f1(f2);// f2 当成是一个普通的参数来使用(形参来使用)

      // setInterval(f2,1000);// 把f2 当成是一个普通参数  传递给别人使用

      //  const btn=document.querySelector("button");
      //  btn.addEventListener("click",f2);// f2 也是高阶函数

      // function getIndex() {
      //   let index=0;
      //   return function () {
      //       index++;
      //       console.log(index);
      //   }
      // }
      // const ff=getIndex();
      // ff();

    </script>

2、 回调函数

如果将函数 A 做为参数传递给函数 B 时,我们称函数 A 为回调函数

简单理解: 当一个函数当做参数来传递给另外一个函数的时候,这个函数就是回调函数

常见的使用场景:

1649164669703

环境变量

环境对象

环境对象指的是函数内部特殊的变量 this ,它代表着当前函数运行时所处的环境

作用:弄清楚this的指向,可以让我们代码更简洁

函数的调用方式不同,this 指代的对象也不同

【谁调用, this 就是谁】 是判断 this 指向的粗略规则

直接调用函数,其实相当于是 window.函数,所以 this 指代 window

    <script>
        let obj = {
            userName:'悟空',
            sayHi:function(){
                console.log(this.userName);
            }
        }
	// obj.sayHi(); // this = ?? this意思是自己 也就是obj  this.userName = '悟空'
        //在前端的js中,我们的全局变量,可以理解为是window的一个属性 window 是默认就存的一个全局变量 console.log(window);
        // window比较特殊,我们想要使用window的一些功能的时候 是可以省略 window
    </script>

排他思想

当前元素为A状态,其他元素为B状态 使用:

  1. 干掉所有人 使用for循环
  2. 复活他自己 通过this或者下标找到自己或者对应的元素
    <style>
        ul{
            list-style: none;
            display: flex;
            margin: 100px auto;
        }
        li{
            display: flex;
            justify-content: center;
            align-items: center;
            width: 100px;
            height: 100px;
            border: 1px solid #000;
        }
    </style>
</head>
<body>
    <ul>
        <li class="active">大家好我是1</li>
        <li>战争片</li>
        <li>动作片</li>
        <li>玄幻片</li>
        <li>爱情片</li>
        <li>神话片</li>
        <li>恐怖片</li>
        <li>家庭伦理剧</li>
    </ul>
    <script>
        let lis = document.querySelectorAll('li')
        console.log(lis);
        for (let index = 0; index < lis.length; index++) {
            // 设置所有li标签的绑定事件
            lis[index].addEventListener("click", function(){
                // 设置所有的li标签为白色
                for (let j = 0; j < lis.length; j++) {
                    lis[j].style.backgroundColor = '#fff'
                }
                // 设置点击自己变成红色
                this.style.backgroundColor = 'red'
            })
        }
    </script>

节点操作

1.1 DOM节点

DOM节点

DOM树里每一个内容都称之为节点

节点类型

元素节点 : 所有的标签 比如 body、 div html 是根节点

属性节点 : 所有的属性 比如 href

文本节点 : 所有的文本
其他

1649227312129

1.2 查找节点

节点关系: 父节点 子节点 兄弟节点

父节点查找: parentNode 属性
返回最近一级的父节点 找不到返回为null

语法

子元素.parentNode

console.dir(pic1.parentNode);

关闭二维码案例

需求:多个二维码,点击谁,谁关闭

分析:

①:需要给多个按钮绑定点击事件

②:关闭的是当前的父节点

    <div>
        <img src="./微信图片_20220406150129.png" class="pic1">
        <img src="./微信图片_20220406150310.png">
    </div>
    <div>
        <img src="./微信图片_20220406150129.png" class="pic1">
        <img src="./微信图片_20220406150310.png">
    </div>
    <div>
        <img src="./微信图片_20220406150129.png" class="pic1">
        <img src="./微信图片_20220406150310.png">
    </div>
    <div>
        <img src="./微信图片_20220406150129.png" class="pic1">
        <img src="./微信图片_20220406150310.png">
    </div>
    <script>
        let pic1 = document.querySelectorAll('.pic1')
        for (let index = 0; index < pic1.length; index++) {
            pic1[index].addEventListener('click', function(){
                this.parentNode.style.display = 'none'
            })
        }
    </script>

子节点查找: childNodes

获得所有子节点、包括文本节点(空格、换行)、注释节点等

children (重点)

仅获得所有元素节点 返回的还是一个伪数组

语法

父元素.children

    <style>
        * {
          margin: 0;
          padding: 0;
          box-sizing: border-box;
        }
        ul{
          background-color: aqua;
          padding: 20px;
          margin-bottom: 10px;
        }
        li{
          height: 30px;
          background-color: yellow;
        }
      </style>
</head>
<body>
    <ul>
        <li>a1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
      </ul>
    <ul>
        <li>b1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
    </ul>
    <ul>
        <li>c1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
    </ul>
    <script>
            // this = 当前被点击的ul标签
            // this.children 获取到所有的ul的子元素 数组
            // 遍历 children 获取到中的每一个li标签
            // li.style.display='none'

        // 1、获取到所有的ul标签 数组
        let uls = document.querySelectorAll('ul')
        // 2、遍历ul数组 挨个绑定点击事件
        for (let index = 0; index < uls.length; index++) {
            // 3、点击事件触发
            uls[index].addEventListener('click', function(){
                // 对被点击的ul的children 做遍历
                for (let j = 0; j < this.children.length; j++) {
                    // this.children[j] 表示每一个li标签
                    this.children[j].style.display='none'
                }
            })
        }
    </script>

兄弟关系查找:

  1. 下一个兄弟节点 : nextElementSibling 属性

  2. 上一个兄弟节点 : previousElementSibling 属性

      <script>
          let lis = document.querySelectorAll('li')
          for (let index = 0; index < lis.length; index++) {
              lis[index].addEventListener('click', function(){
                //   previousElementSibling 上一个兄弟 变蓝
                  this.previousElementSibling.style.backgroundColor = 'blue'
                //   nextElementSibling 下一个兄弟 被绿了
                  this.nextElementSibling.style.backgroundColor = 'green'
              })
          }
      </script>

1.3 增加节点

很多情况下,我们需要在页面中增加元素

比如,点击发布按钮,可以新增一条信息

一般情况下,我们新增节点,按照如下操作:

创建一个新的节点 把创建的新的节点放入到指定的元素内部

学习路线: 创建节点 追加节点

1.创建节点

即创造出一个新的网页元素,再添加到网页内,一般先创建节点,然后插入节点

创建元素节点方法:

createElement(标签名) 设置增加的节点 

2.追加节点

要想在界面看到,还得插入到某个父元素中

插入到父元素的最后一个子元素:

父元素.appendChild(要插入的元素) 把增加的元素添加进去 如果本来就有 就添加在最后面

插入到父元素中某个子元素的前面

父元素.insertBefore(要插入的元素, 在那个元素前面插入)

演示

    <ul></ul>
    <script>
        let uls = document.querySelector('ul')
        // createElement(标签名) 设置增加的节点 
        let li = document.createElement('li')
        // 父元素.appendChild(要插入的元素)  把增加的元素添加进去 如果本来就有 就添加在最后面
        uls.appendChild(li)
        li.innerText = 'halo'
        li.style.backgroundColor = 'green'
    </script>

案例

    <ul class="left">
        <li>龙虾</li>
        <li>鲍鱼</li>
        <li>皇帝蟹</li>
        <li>鱼子酱</li>
    </ul>
    <ul class="right">
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
    <script>
        // insertBefore 也能插入元素 功能也类似 appendchild
        // 如果要插入的元素 是已经存在的 那么insertBefore作用 移动
        // 如果要插入的元素 是新创建的 那么insertBefore作用 仅仅是插入
        let c = document.querySelector('.left li:nth-child(3')
        let two = document.querySelector('.right li:nth-child(2')
        let right = document.querySelector('.right')
        // 父元素.insertBefore(要插入的元素, 在那个元素前面插入)
        right.insertBefore(c, two)

        let li = document.createElement('li')
        li.innerText = '新创建的'
        right.insertBefore(li, two)
    </script>

1649291027401

1.4 克隆节点

特殊情况下,我们新增节点,按照如下操作:

复制一个原有的节点 把复制的节点放入到指定的元素内部

克隆节点

1649303654765

cloneNode会克隆出一个跟原标签一样的元素,括号内传入布尔值

若为true,则代表克隆时会包含后代节点一起克隆--深拷贝

若为false,则代表克隆时不包含后代节点--浅拷贝 默认为false

    <div class="box">
        <button>点击</button>
        <img src="../微信图片_20220405203436.jpg" alt="">
    </div>
    <script>
        // 1 克隆节点 box
        let box = document.querySelector('.box')
        // 2 开始克隆
        // let newBox = box.cloneNode() // 浅克隆 不会把div的后代节点一起克隆
        let newBox = box.cloneNode(true) // true 深克隆 会把div的后代节点一起克隆
        // 插入到body标签中
        document.body.appendChild(newBox)
    </script>

1.5 删除节点

若一个节点在页面中已不需要时,可以删除它

在 JavaScript 原生DOM操作中,要删除元素必须通过父元素删除

语法

1649303667980

注: 如不存在父子关系则删除不成功

删除节点和隐藏节点(display:none) 有区别的:

隐藏节点还是存在的,但是删除,则从html中删除节点

<body>
    <button>删除</button>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
        <li>6</li>
    </ul>
    <script>
        let button = document.querySelector('button')
        let uls = document.querySelector('ul')
        // 要删除的子元素
        // let li = document.querySelector('li:nth-child(1)') // 写外面 删除li里面的第一个标签 固定第一个元素
        button.addEventListener('click', function(){
            // 写在里面 每一次点击按钮的时候 都是重新拿ul中的第一个li
            let li = document.querySelector('li:nth-child(1)') 
            // 要删除的指定元素
            uls.removeChild(li)

            // 删除自己
            // uls.remove()
        })
    </script>

综合案例渲染一

    <link rel="stylesheet" href="./style.css" />
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
    </style>
  </head>
  <body>
    <!-- 来引入外部的js -->
    <script src="./data/data.js"></script>    
      // 定义变量 用来最终显示 标签
      // 开头
      let html = `
      <div class="box w">
  <div class="box-hd">
    <h3>精品推荐</h3>
    <a href="#">查看全部</a>
  </div>
  <div class="box-bd">
    <ul class="clearfix">
      `;
      // 中间需要遍历
      for (let index = 0; index < data.length; index++) {
        // 在循环li标签的时候  可以动态传入对应图片和文字内容! 
        html += `
        <li>
        <img src="${data[index].src}" alt="" />
        <h4>
          ${data[index].title}
        </h4>
        <div class="info">
          <span>高级</span> • <span>${data[index].num}</span>人在学习
        </div>
      </li>
        `;
      }
      // 结尾
      html += `
    </ul>
  </div>
</div>
      `;
      // 把拼接好的html 显示到网页中
      document.write(html);
    </script>

综合案例渲染二

    <link rel="stylesheet" href="./style.css" />
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
    </style>
  </head>
  <body>
    <div class="box w">
        <div class="box-hd">
          <h3>精品推荐</h3>
          <a href="#">查看全部</a>
        </div>
    
        <div class="box-bd">
            <ul class="list clearfix"></ul>
        </div>
    </div>
    <!-- 来引入外部的js -->
    <script src="./data/data.js"></script>
    <script>
        let ul = document.querySelector('.list')
        for (let index = 0; index < data.length; index++) {
            
            let li = document.createElement('li')
            let img = document.createElement('img')
            img.src = data[index].src
            let h4 = document.createElement('h4')
            h4.innerText = data[index].title
            let div = document.createElement('div')
            div.classList.add('info')
            let span1 = document.createElement('span1')
            span1.innerText = '高级'
            let span2 = document.createElement('span2')
            span2.innerText = data[index].num
            let text1 = document.createTextNode('•')
            let text2 = document.createTextNode('人在学习')
            // 节点的类型 元素节点(标签) 文本节点

            // 开始组装 append 可以同时插入多个标签
            // appendChild 只能插入一个标签
            div.append(span1, span2)
            li.append(img, h4, div)
            ul.appendChild(li)
        }
        
    </script>