JS基础-事件处理

76 阅读1分钟

事件处理

<button class="btn">按钮</button>

<script>
    var btnEl = document.querySelector('.btn')
    btnEl.addEventListener('click',function () {
        console.log('第一个事件监听');
    })
    btnEl.addEventListener('click',function () {
        console.log('第二个事件监听');
    })
</script>

事件冒泡、捕获

事件是从最内层向外依次传递,这个顺序称之为事件冒泡, 从外层到内层这种称之为事件捕获

<div class="box">
    <span class="word"></span>
</div>

<script>
    var bodyEl = document.body
    var divEl = document.querySelector('.box')
    var spanEl = document.querySelector('.word')

    // true:设置监听事件捕获的过程,默认是事件冒泡
    bodyEl.addEventListener('click',function () {
        console.log('body被点击了');
    },true)
    
    divEl.addEventListener('click',function () {
        console.log('div被点击了');
    },true)
    
    spanEl.addEventListener('click',function () {
        console.log('span被点击了');
    },true)
</script>

当一个事件发生时,就会有和这个事件相关的很多信息:这些信息会被封装到一个Event对象中,这个对象由浏览器创建,称之为event对象

<div class="box">
    <button class="btn">按钮</button>
</div>

<script>
    var divEl = document.querySelector('.box')
    var btnEl = document.querySelector('.btn')

    // 获取event对象
    divEl.onclick = function (event) {
        console.log(event);
    }
</script>

event常见的属性和方法:

<div class="box">
    <button class="btn">按钮</button>
</div>

<script>
    var divEl = document.querySelector('.box')
    var btnEl = document.querySelector('.btn')

    divEl.onclick = function (event) {
        console.log(event.type); // 事件类型: click
        console.log(event.offsetX,event.offsetY); // 事件发生在元素内的位置
        console.log(event.screenX, event.screenY); // 事件发生相对于屏幕的位置

        // currentTarget/target
        console.log(event.target); // 事件发生的对象
        console.log(event.currentTarget); // 当前处理的对象
        console.log(event.target === event.currentTarget); // 当事件冒泡时就会有区别
    }
    
    divEl.addEventListener('click',function (event) {
        event.preventDefault() // 阻止默认行为
        event.stopPropagation() // 阻止事件的进一步传递(冒泡或者捕获都可以阻止)
        console.log(this === event.target); // true
    })
</script>

EventTarget类:

EventTarget是一个DOM接口,主要用于添加、删除、派发Event事件

<button class="btn">按钮</button>

<script>
    var btnEl = document.querySelector('button')

    var foo = function () {
        console.log('监听按钮的点击');
    }
    btnEl.addEventListener('click', foo)

    // 过5秒后将事件监听移除
    setTimeout(function () {
        console.log('将事件监听移除');
        btnEl.removeEventListener('click', foo)
    }, 5000)

    // eventTarget本身就可以实现类似于事件总线的效果
    window.addEventListener('www', function () {
        console.log('监听www的事件');
    })
    setTimeout(() => {
        window.dispatchEvent(new Event('www')) // 自己派发一个事件
    }, 2000)
</script>

事件委托

当子元素被点击时,父元素可以通过冒泡可以监听到子元素的点击;并可以通过event.target获取到当前监听的元素

  • 一个ul中存放多个li,点击某一个li会变成红色
<style>
    .active {
        color: orange;
        font-size: 15px;
    }
</style>
<body>
<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
</ul>

<script>
    // 需求一:一个ul中存放多个li,点击某一个li会变成红色
        var liEls = document.querySelectorAll("li")
        // 每一个li都箭头自己的点击
        for (var liEl of liEls) {
            liEl.onclick = function() {
                this.classList.add('active')
               // event.currentTarget.classList.add('active')
            }
        }
    
        // 事件委托:统一在ul中监听
        var ulEl = document.querySelector('ul')
        ulEl.onclick = function (event) {
            event.target.classList.add('active')
        }

    // 需求二:点击li变成active样式,其他的取消active样式
    var ulEl = document.querySelector('ul')
    var activeLiEl = null
    ulEl.onclick = function (event) {
        // 写法一:1.将之前的active移除
        for (var i = 0; i < ulEl.children.length; i++) {
            if (ulEl.classList.contains('active')) { // 有active才移除
                ulEl.children[i].classList.remove('active')
            }
        }
        // 写法二:1. 找到active之前,移除掉active
        var activeEl = ulEl.querySelector('.active')
        activeEl && activeEl.classList.remove('active') // 有值才会调用

        // 写法三: 1.变量的记录方式(常用)
        if (activeLiEl && event.target !== ulEl) {
            activeLiEl.classList.remove('active')
        }

        // 2.给点击的元素添加active
        if (event.target !== ulEl) {
            event.target.classList.add('active')
        }
        // 3.记录最新的active对应的li
        activeLiEl = event.target
    }
</script>
</body>
  • 多个按钮的点击,区分点击了哪一个按钮
<div class="btnList">
    <button data-active="create">新建</button>
    <button data-active="del">删除</button>
</div>
<script>
    var btnList = document.querySelector('.btnList')
    btnList.addEventListener('click',function (event) {
        var active = event.target.dataset.active // 拿到active
        switch (active) {
            case 'create':
                console.log('点击了新建按钮');
                break
            case 'del':
                console.log('点击了删除按钮');
                break
        }
    })
</script>

常见的鼠标事件

image.png

常见的表单事件

image.png

案例

  • 定时器

setTimeout:n秒后再执行函数

setInterval: 重复运行一个函数,每过n秒调用一次函数

clearTimeout:取消setTimeout的定时器;

clearInterval:取消setInterval的定时器

<button class="out">取消setTimeout定时器</button>
<button class="itv">取消setInterval定时器</button>
<script>
  function foo(name,age) {
    console.log('执行函数',name,age);
  }
  var timeId = setTimeout(foo,2000,'www',19) // 2秒后再执行函数,可以传递参数

  var timeClearEl = document.querySelector('.out')
  timeClearEl.onclick = function () {
    clearTimeout(timeId) // 取消调度
  }


  function bar() {
    console.log('执行函数');
  }
  var itvId = setInterval(bar,3000) // 每过三秒调用一次函数

  var itvEl = document.querySelector('.itv')
  itvEl.onclick = function () {
    clearInterval(itvId)
  }
</script>