Javascript 事件监听

1.addEventListener()

  • 语法:node.addEventListener(事件名称,回调函数,是否使用事件捕获传递)
  • 第三个参数:可以是布尔值,就用来描述是否使用事件捕获传递,默认为false,即冒泡传递,如果设为true,则代表为捕获传递,也可以是一个配置对象
<script>
    var ul = document.querySelector('ul')
    //冒泡传递
    ul.addEventListener('click',function(){
        console.log('点击了ul 冒泡传递')
    })
    //捕获传递
    ul.addEventListener('click',function(){
        console.log('点击了ul 捕获传递 - 1')
    },true)
    //捕获传递
    ul.addEventListener('click',function(){
        console.log('点击了ul 捕获传递 - 2')
    },{capture: true})

    //只执行一次
    var button = document.querySelector('button')
    button.addEventListener('click',function(){
        console.log('点击了button')
    },{once: true})
</script>
  • 此方式可以给同一个Dom元素的同一事件绑定多个回调(但是不能是同一个事件回调,多余的添加将自动被去除)
var ul = document.querySelector('ul')
    ul.addEventListener('click',function(){
        console.log('点击了ul')
    })
    ul.addEventListener('click',function(){
        console.log('点击了ul - 2')
    })

  • 兼容性:Internet Explorer 8 及更早IE版本不支持 addEventListener() 方法,,Opera 7.0 及 Opera 更早版本也不支持,解决办法
function addEvent(obj,type,func){
    if (obj.addEventListener) {
        obj.addEventListener(type, func,false);
    } else {
        obj.attachEvent("on"+type, func);
    }
}

function  removeEvent(obj,type,func){
    if (obj.removeEventListener) {
        obj.removeEventListener(type, func,false);
    } else {
        obj.detachEvent("on"+type, func);
    }
}

2.on + 事件名称

  • 直接在标签中通过 on + 事件名称 添加事件监听
<p onclick="someFn()">11111</p>
  • 通过Dom元素赋值属性的形式添加
document.querySelector('p').onclick=someFn
  • 上面2种方法操作的是同一个东西,都是对Dom的属性进行定义,所以相互直接会覆盖(最终生效的只有test3)
var ul = document.querySelector('ul')
    ul.onclick = test2
    ul.onclick = test3

    function test(){
        console.log('test')
    }
    function test2(){
        console.log('test2')
    }
    function test3(){
        console.log('test3')
    }
  • on + 事件名称使用的是冒泡传递
<body>
    <ul onclick="test('ul')">
        <li onclick="test('li')">
            <p onclick="test('p')">1111</p>
        </li>
    </ul>
</body>
</html>
<script>
    function test(msg){
        console.log(msg)
    }
</script>

点击这个区域,依次打印(事件由内到外传递)

p
li
ul

3.查看元素所绑定的事件

  • F12->选择Dom元素->事件监听器(元素所有绑定的事件都在此显示,包括自定义事件)

4.移除事件监听

  • 还可以直接通过UI界面进行移除
  • Js方式移除:removeEventListener(事件名称,回调名称)
  • 注意:只能移除addEventListener()方法添加的事件,且事件回调,传递机制要一样(也就是说回调方法不能是匿名)
// 向 <div> 元素添加事件句柄
document.getElementById("myDIV").addEventListener("click", myFunction);

// 移除 <div> 元素的事件句柄
document.getElementById("myDIV").removeEventListener("click", myFunction);

5.冒泡与捕获

  • 事件基本流程:多个元素相互嵌套,事件一旦触发,最外层的元素最先感知,然后依次传递给自己的子元素,而一直传递到最内层的元素后,会反方向依次传递给父元素
  • 冒泡与捕获:由外到内的这个过程叫做捕获,由内到外这个过程叫做冒泡
  • 触发时机:只能在捕获和冒泡两个过程中选一个时机执行回调,使用冒泡机制就是在冒泡的过程中才执行,使用捕获机制就是在捕获过程中执行,不理解可以看图

  • 通俗的说,冒泡就是先执行内层元素事件,再外层元素事件,而捕获则相反,先执行外层元素事件,再执行内层元素事件
  • 以上的内容由个人测试总结而来,不保证专业(测试代码已删)

6.事件触发

  • 事件名称 + ():原生事件可以通过该方式进行触发(click,focus,blur),不同方式添加的事件监听都能执行(onclick/addEventListener),还支持冒泡,默认事件需要有相关的用户动作才能执行
<body>
    <div id="box">
        <ul>
            <li>列表</li>
        </ul>

    </div>
    <a href="https://www.baidu.com" target="_blank">百度一下</a>

    <button>点我</button>
</body>
<script>
    //外层元素
    var ul = document.querySelector("ul")
    //外层事件监听
    ul.onclick = function(){
        console.log("onclick ul")
    }
    ul.addEventListener("click",function(){
        console.log("addEventListener ul")
    })

    //触发外层元素点击事件(原生事件)
    ul.click()
    //输出onclick ul
    //输出addEventListener ul

    console.log('---')

    //内层元素
    var li = document.querySelector("li")
    //内层事件监听
    li.addEventListener("click",function(){
        console.log("addEventListener li")
    })
    //触发内层元素点击事件(原生事件),说明支持冒泡
    li.click()
    //输出addEventListener li
    //输出onclick ul
    //输出addEventListener ul


    //默认事件测试
    var link = document.querySelector("a")
    //模拟点击
    setTimeout(() => {
        //模拟点击
        link.click() //弹窗被阻止,默认事件不支持
    }, 1000)

    //点击其他位置来模拟改链接点击链接
    document.querySelector('button').onclick = function(){
        //点击button按钮,进入此事件回调,因为有点击动作,虽然点的不是当前链接标签,但是此次默认事件可以执行
        link.click()
    }
</script>
  • 通过创建事件对象来模拟触发,可以设定此次触发时是否冒泡机,是否可以阻止默认事件等等
<body>
    <div class="box">
        <ul>
            <li>li</li>
        </ul>
    </div>

    <button onclick="triggerClick(false)">bubbles:false</button>
    <button onclick="triggerClick(true)">bubbles:true</button>
</body>
<script>
    var box = document.querySelector('.box')
    var ul = document.querySelector('ul')
    var li = document.querySelector('li')

    //box事件监听
    box.addEventListener('click',function(e){
        console.log('click box - 冒泡')
    },false)
    box.addEventListener('click',function(e){
        console.log('click box - 捕获')
    },true)

    //ul事件监听
    ul.addEventListener('click',function(e){
        console.log('click ul - 冒泡')
    },false)
    ul.addEventListener('click',function(e){
        console.log('click ul - 捕获')
    },true)

    //li事件监听
    li.addEventListener('click',function(e){
        console.log('click li - 冒泡')
    },false)
    li.addEventListener('click',function(e){
        console.log('click li - 捕获')
    },true)


    //按钮监听回调
    function triggerClick(bubbles = false){
        console.log('bubbles = ',bubbles)
        //创建事件对象
        var ev = new Event(
            'click',
            {
                'bubbles': bubbles,//表示是否冒泡,默认false,false表示不会触发其外层元素在冒泡阶段的回调事件,则true则表示会
                'cancelable': false,//经测试效果未知
            }
        )

        //模拟触发
        ul.dispatchEvent(ev)
    }
</script>

  • 自定义事件的定义和触发
<script>
    var box = document.querySelector(".box")
    //自定义事件,移除当前元素的子元素
    box.addEventListener('removeChild',function(event,index){
        //第一个参数为event
        console.log(event) //CustomEvent{}
        var children = this.children
        this.removeChild(children[1])
    })
    var event = new CustomEvent('removeChild', { bubbles:true,cancelable:true }) //使用冒泡机制 允许用户禁止
    box.dispatchEvent(event,1)
</script>
posted @ 2019-09-25 16:40  ---空白---  阅读(653)  评论(0编辑  收藏  举报