JavaScript(11) - 阻止事件冒泡和默认行为,拖拽,事件监听器

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一、阻止事件冒泡和默认行为

事件流
事件流是描述的从页面接受事件的顺序,当几个都具有事件的元素层叠在一起的时候, 那么你点击其中一个元素,并不是只有当前被点击的元素会触发事件,而层叠在你点击范围的所有元素都会触发事件。事件流包括两种模式:冒泡和捕获。

事件冒泡
事件冒泡是从里往外逐个触发. 事件捕获, 是从外往里逐个触发. 现代的浏览器默认情况下都是事件冒泡的模式.
冒泡传递事件

document.onclick=function(){ 
      console.log('我是 document'); 
}; 
document.documentElement.onclick=function() { 
      console.log('我是 html'); 
}; 
document.body.onclick= function(){ 
      console.log('我是 body'); 
};
document.getElementById('box').onclick=function() { 
      console.log('我是 div'); 
}; 
document.getElementsByTagName('input')[0].onclick= function(){
      console.log('我是 input'); 
};

但是一般我们只在指定的节点上添加事件, 而不想让其传递到下层节点触发事件, 这样我们就需要阻止事件冒泡;

阻止事件冒泡有两个方法:
( 在指定不想再继续传递事件的节点的事件执行函数中使用)

1, 取消冒泡, IE

 e.cancelBubble = true; 

2, 停止传播, 非IE

 e.stopPropagation(); 

例如:

document.getElementsByTagName('input')[0].onclick= function(evt){
     var e = evt || window.event;
     //可以通过下述两个方法取消事件冒泡
     if(e.stopPropagation){
	e.stopPropagation();
     }else{
     	e.cancelBubble = true 
     };

阻止浏览器默认行为

  if (e.preventDefault) {
e.preventDefault();   //非IE
  }
  else {
          e.returnValue = false;  // IE
  }

阻止右键菜单
在之前使用event对象的button属性时, 点击鼠标右键会弹出系统菜单, 如果我们想要创建自己的右键菜单, 则需要先阻止默认的右键菜单

document.oncontextmenu = function(){
      console.log("右键被按下");
      return false;
}

标签有属性href, 在用户点击超链接标签时, 实际上内部会调用onclick事件,那么如果我们需要在超链接跳转前做一些判断处理, 则可以将onclick指向我们自己的函数,并返回true或者false来决定是否允许超链接跳转;

例如:

var oA = document.getElementsByTagName("a")[0];
oA.onclick = function() {
      if(confirm("你确定要跳转吗?")) {
            return true;
      }
      else {
            return false;
      }
}
<a href=“http://www.baidu.com”>百度一下</a>

二、拖拽

所谓拖拽: 就是按住元素后移动位置, 最后松开的过程

1, 实现拖拽相关的三大事件:

onmousedown : //鼠标按下
onmousemove : //鼠标移动
onmouseup : //鼠标松开

2, 实现拖拽思路:

1, 给目标元素添加onmousedown事件(鼠标按下事件)
在鼠标按下的瞬间, 记录鼠标所在位置与目标元素左边界的距离disX, 以及与上边界的距离disY
2, 当onmousedown事件发生以后(鼠标按下后),就给document添加onmousemove事件(鼠标移动事件)在onmousemove(鼠标移动事件)中, 根据以下公式不断刷新目标元素所在的位置:

公式: 目标元素的left = oEvent.clientX – disX + “px”;
目标元素的top = oEvent.clientY – disY + “px”;

3, 在onmousedown事件(鼠标按下事件)发生以后,给document再添加onmouseup事件(鼠标松开事件),且在onmouseup事件中,取消document的onmousemove事件;

注意:
onmousedown触发事件的对象: 目标元素(即要拖拽的元素);
onmousemove触发事件的对象: document
onmouseup触发事件的对象: document

onmousemove和onmouseup的触发事件对象都是document, 意味着鼠标在网页的任意位置移动鼠标或松开鼠标,都会触发对应的事件;

onmousemove和onmouseup 都要写在onmousedown事件中, 这样就可以保证鼠标按下后才可以移动目标元素(onmousemove)或停止移动(onmouseup)

onload = function() {
    var box = document.getElementById("box");
    //鼠标按下
    box.onmousedown = function(evt) {
        var e = evt || event;
        //计算鼠标位置与div左边和上边的距离
        var disX = e.clientX - box.offsetLeft;
        var disY = e.clientY - box.offsetTop;
        //鼠标移动
        document.onmousemove = function(evt) {
            var e = evt || event;
            box.style.left = e.clientX - disX + "px";
            box.style.top = e.clientY - disY + "px";
        }
        //鼠标松开
        document.onmouseup = function() {
            document.onmousemove = null;
            document.onmouseup = null;
        }
    }
}
获取style样式
if (window.getComputedStyle) {
    style = window.getComputedStyle(box, null);    //支持IE9+及非IE浏览器
} else { 
    style = box.currentStyle;  // IE8及以前
} 

三、事件监听器

事件监听器:

  事件监听器, 是JS事件中的一种事件触发机制, 我们可以通过添加事件监听器的方式给元素添加事件及执行函数

1, 添加事件监听器

box.addEventListener(“click”, func, false) : 给box元素添加点击事件(click), 以及事件执行函数func. 针对该函数的三个参数作说明:
第一个参数(“click”) : 事件名称(前面没有on)
第二个参数(func): 事件执行函数名称(没有双引号, 也没有())
第三个参数(false/true) : 是否使用捕捉(反向冒泡),默认false,为冒泡

2, 移除事件监听器

box.removeEventListener(“click”, func) : 将box元素的点击事件(click), 以及对应的事件执行函数func移除
注: 这里只会删除使用box.addEventListener()方法添加的事件监听器

注: IE8及其以下不支持,火狐和谷歌支持。

事件监听器:

  • 在IE8及以下的浏览器中, 我们可以使用以下方式:
box.attachEvent("onclick", fn);   //添加事件
box.detachEvent("onclick", fn);   //移除事件
  • 封装事件监听器, 兼容IE浏览器, 谷歌, 火狐
//添加事件
function addEvent(obj, type, fn, useCapture){
      if (obj.addEventListener) {  
	obj.addEventListener(type, fn, useCapture);
      }
      else {
	obj.attachEvent("on"+type, fn);
      }
}
//移除事件
function removeEvent(obj, type, fn, useCapture){
      if (obj.removeEventListener) {
	obj.removeEventListener(type, fn, useCapture);
      }
      else {
	obj.detachEvent("on"+type, fn);
      }
}
//调用
addEvent(aBtn[0], "click", fn, false);
function fn(){
      alert("click 按钮1");
}
aBtn[1].onclick = function(){
      removeEvent(aBtn[0], "click", fn, false);
}

笔记代码

1.阻止默认事件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <a href="http://www.baidu.com">a标签</a>
    <!-- a标签默认会跳转页面 -->
    <script>
        document.getElementsByTagName('a')[0].onclick = function(e){
            console.log("点击了");
            // return false 阻止默认行为 遵从w3c但是ie9浏览器之前不支持(常用的)
            return false
            //ie浏览器 兼容 其他浏览器也可以使用
            e.preventDefault()//阻止默认事件\
            //针对低版本浏览器
            e.returnValue = false
        }
    </script>
</body>
</html>

2.阻止冒泡事件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #bigBox{
            width: 500px;
            height: 500px;
            background-color: aqua;
        }
        #box{
            width: 200px;
            height: 200px;
            background-color: chartreuse;
        }
    </style>
</head>
<body>
    <div id="bigBox">
        <div id="box">
            <button id="btn">点击</button>
        </div>
    </div>

    <script>
        var box = document.getElementById("box")
        var btn = document.getElementById("btn")
        var bigBox = document.getElementById("bigBox")
        box.onclick = function(){
            console.log("按钮盒子被点击了");
        }
        //在点击div里面的按钮时 会触发div的点击事件 事件冒上去了
        //在触发事件的时候 会一层一层向上冒泡 (他同时会触发父类的事件)
        //阻止事件冒泡 意思就是阻止事件的向上传递
        btn.onclick = function(e){
            //得到事件源对象
            e = e || window.event
    
            //阻止事件向上冒泡 stopPropagation 这个方法可以阻止事件冒泡 且遵从w3c规则 (兼容各大浏览器 ie9之前不兼容)
            e.stopPropagation()
            
            //ie浏览器的阻止事件冒泡 利用一个属性 cancelBubble 设置为true 他也兼容各大浏览器(不遵从w3c规范)
            // e.cancelBubble = true //取消冒泡 不建议写
            // 建议写法
            if(e.stopPropagation){//如果浏览器可以使用
                e.stopPropagation()//就使用这个

            }else{
                e.cacelBubble = true //如果不能使用就使用这个
            }
            
            console.log("点击了按钮");
        }
        bigBox.onclick = function(){
            console.log("大盒子被点击了");
        }
    </script>
</body>
</html>

3.实现拖拽

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{margin: 0;padding: 0;}
        .bigBox{
            width: 500px;
            height: 500px;
            background-color: pink;
            position: absolute;
            left: 100px;
            top: 50px;
        }
        #box{
            width: 100px;
            height: 100px;
            background: red;
            position: absolute;
        }
    </style>
</head>
<body>
    
    <div class="bigBox">
        <div id="box">

        </div>
    </div>

    <script>
        //实现拖拽
        //鼠标按下(onmousedown) 然后鼠标移动(onmousemove) 就会跟着动 鼠标松开(onmouseup)就不动了
        // offset家族的内容 只读
        var box = document.getElementById("box")
        var bigBox = document.getElementsByClassName("bigBox")[0]
        box.onmousedown = function(){
            box.onmousemove = function(e){
                e = e || window.event
                //获取大盒子的偏移
                var bigx = bigBox.offsetLeft
                var bigy = bigBox.offsetTop
                //获取鼠标的位置
                var mouseX = e.pageX
                var mouseY = e.pageY
                //中心点要要减去的高宽
                var w = box.offsetWidth/2
                var h = box.offsetHeight/2
                //定位设置left值和top值
                var left = mouseX - w - bigx// 鼠标坐标-原本的宽度的一半-大盒子的偏移量
                var top = mouseY - h - bigy
                this.style.left = left+"px"
                this.style.top = top+"px"
                //里面盒子的偏移量
                var x = box.offsetLeft
                var y = box.offsetTop
                //区间设置
                if(x<0){
                    this.style.left = "0px"
                }
                if(y<0){
                    this.style.top = "0px"
                }
                // x y 的最大区间设置
                if(x>bigBox.offsetWidth-w*2){
                    this.style.left = bigBox.offsetWidth-w*2 + "px"

                }
                if(y>bigBox.offsetHeight-h*2){
                    this.style.top = bigBox.offsetHeight-h*2 + "px"
                }
            }
        }
        //鼠标弹起事件
        box.onmouseup = function(){
            box.onmousemove = function(){

            }
        }
    </script>
</body>
</html>

4.练习

1.练习1

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{margin: 0;padding: 0;}
        #box{
            width: 500px;
            height: 500px;
            background-color: aqua;
            display: flex;
            justify-content: center;
            align-items: center;
            margin: 10px auto;
        }
        #box1{
            width: 100px;
            height: 100px;
            font-size: 16px;
            background-color: darkgoldenrod;
            margin-right: 10px;
           
        }
        #box2{
            width: 100px;
            height: 100px;
            font-size: 16px;
            background-color: darkorange;
            margin-left: 10px;
        }
    </style>
</head>
<body>
    <div id="box">
        <div id="box1">嗨害嗐</div>
        <div id="box2">测试测试测试测试测试</div>
    </div>

    <script>
        // 一个盒子里面有俩个小盒子 
        var box = document.getElementById("box") 
        var box1 = document.getElementById("box1") 
        var box2 = document.getElementById("box2") 
       
        
         // 右键点击第一个小盒子换颜色 
        box1.onmousedown = function(e){
            e.stopPropagation?e.stopPropagation:e.cancelBubble = true
            if(e.button == 2){
                this.style.backgroundColor = "#ccc"
            }
        }
        // 右键点击第二个小盒子 变内容 
        box2.onmousedown = function(e){
            e.stopPropagation?e.stopPropagation:e.cancelBubble = true
            if(e.button == 2){
                this.innerText = "我是改变了的内容"
            }
        }
        // 点击大盒子改字体颜色
        box.onmousedown = function(){
            this.style.color = "red"
            // box.style.color = "red"
           
            // e = e || window.event
            // if( e.stopPropagation){
            //     e.stopPropagation()
            // }else{
            //     e.cancelBubble = true
            // }
            e.stopPropagation?e.stopPropagation:e.cancelBubble = true
        }


        //事件 右键出现菜单 oncontextmenu 的事件
        document.oncontextmenu = function(e){
            // return false 后面的内容不会执行 return false一般放在最后一句
            //如果第一个可以用就用第一个 不可以使用第二个
            e.preventDefault?e.preventDefault():(e.returnValue=false)
        }
    </script>
</body>
</html>

2.练习2

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box{
            width: 500px;
            height: 500px;
            background-color: aquamarine;
            position: absolute;
            margin: 10px;
        }
        .header{
            width: 100%;
            height: 50px;
            background-color: blueviolet;
        }
        .content{
            width: 100%;
            height: 450PX;
            background-color: coral;
             
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="header"><span id="close">关闭</span></div>
        <div class="content"></div>
    </div>

    <script>
        //1.窗口拖动和关闭,只可以点击紫色区域才可以拖拽窗口,点击关闭按钮就关闭窗口
        var box = document.getElementsByClassName("box")[0]//大盒子
        var header = document.querySelector('.header')
        //获取第一次的偏移量
        var firstL = box.offsetLeft
        var firstT = box.offsetTop
        header.onmousedown = function(e){
            //键盘按下的时候获取值
            e = e || window.event
            // var l = box.offsetLeft
            // var t = box.offsetTop
            
            //得到鼠标在里面的位置 鼠标的位置 - 大盒子的偏移量
            var currentX = e.clientX - box.offsetLeft
            var currentY = e.clientY - box.offsetTop
             
            document.onmousemove = function(e){
                //移动box
                e = e || window.event
                //得到鼠标的坐标
                var x = e.clientX - firstL
                var y = e.clientY - firstT
                box.style.left = x-currentX + "px"
                box.style.top = y-currentY + "px"
            }
        }
        //弹起取消 移动
        header.onmouseup = function(){
            document.onmousemove = null
            document.onmouseup = null
        }
       // 点击事件 处在键盘按下和弹起之后执行
        document.getElementById("close").onmousedown = function(){
            box.style.display = "none"
        }
    </script>
</body>
</html>

总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了 阻止事件冒泡和默认行为,拖拽,事件监听器使用,上面是今天的代码

  • 7
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值