JQuery 事件的绑定解绑、冒泡

323 阅读1分钟

JQ toggle 事件切换

jq对象.toggle(fn1,fn2...)
当单击jq对象对应的组件后,会执行fn1.第二次点击会执行fn2.....

⚠️注意: 1.9版本 .toggle() 方法删除,jQuery Migrate(迁移)插件可以恢复此功能

<script src="https://cdn.bootcdn.net/ajax/libs/jquery-migrate/3.3.2/jquery-migrate.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.8.2/jquery.js"></script>

<input type="button" value="按钮" id="btn">
<script>
  $("#btn").toggle(
    () => { console.log("第一次点击") },
    () => { console.log("第二次点击") },
    () => { console.log("第三次点击") },
  )
</script>

事件的触发

  • 第1种: 对象.事件名字()
  • 第2种: 对象.trigger("事件名字")
  • 第3种: 对象.triggerHandler("事件名字")
<input type="text" id="txt">
<span></span>
<input type="button" value="按钮" id="btn">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.8.2/jquery.js"></script>
<script>

  //文本框添加获取焦点的事件
  $("#txt").focus(function () {
    $(this).next("span").text("文本框获取焦点了")   //设置当前元素的下一个兄弟元素中显示一个提示信息
  })

  //按钮的点及事件
  $("#btn").click(function () {
    //第1种: 调用文本框的获取焦点的事件
    //这种方式让别的元素的事件触发
    $("#txt").focus()

    //第2种: 触发事件的方式
    // $("#txt").trigger("focus")//触发的意思

    //第3种: 可以触发该事件,但不能触发浏览器的默认的行为
    $("#txt").triggerHandler("focus")
  }) 
</script>

事件的绑定

常规: 元素.事件名字(事件处理函数)

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.8.2/jquery.js"></script>

<input type="button" value="按钮" id="btn">
<script>
  $("#btn")
    .mouseenter(function () {
      $(this).css("backgroundColor", "red")
    })
    .mouseleave(function () {
      $(this).css("backgroundColor", "green")
    })
    .click(function () {
      alert("啊~我被点了")
    });
</script>

bind方法绑定事件

元素.bind("事件名字",事件处理函数)

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.8.2/jquery.js"></script>

<input type="button" value="按钮" id="btn">
<script>
  $("#btn")
    .bind("click", function () {
      alert("哦买雷电嘎嘎闹")
    })
    .bind("mouseenter", function () {
      $(this).css("backgroundColor", "red")
    })
    .bind("mouseleave", function () {
      $(this).css("backgroundColor", "green")
    });
</script>

传多个事件共用一个函数

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.8.2/jquery.js"></script>

<div id="btn">
  <input type="button" value="按钮">
</div>
<script>
  $('#btn').bind('mouseover click', function (event) {
    document.body.append($(this).html())
  })
</script>

bind 键值对的方式绑定事件

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.8.2/jquery.js"></script>

<div id="btn">
  <input type="button" value="按钮">
</div>
<script>
  $("#btn")
    .bind({
      "click": function () { alert("哦买雷电嘎嘎闹") },
      "mouseenter": function () { $(this).css("backgroundColor", "red") },
      "mouseleave": function () { $(this).css("backgroundColor", "green") }
    })
</script>

delegate 委派绑定

父元素.delegate("子元素的选择器","事件名字",事件处理函数) 最终事件是在子元素上

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.8.2/jquery.js"></script>

<div id="div">
  <input type="button" value="子元素">
</div>
<input type="button" value="按钮" id="btn" style="margin-top: 10px">

<script>
  $(function () {
    $("#btn").click(function () {
      //子级元素委托父级绑定事件
      //父级元素调用方法,为子级元素绑定事件
      $("#div").delegate("input", "click", function () {
        alert("啊!~,被点了")
      })
    })
  })
</script>

on绑定

父级对象.on("事件名字","子级元素",事件处理函数)

<ul>
  <li>这是第1个 li 标签</li>
  <li>这是第2个 li 标签</li>
  <li>这是第3个 li 标签</li>
  <li>这是第4个 li 标签</li>
  <li>这是第5个 li 标签</li>
</ul>

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.8.2/jquery.js"></script>
<script>
  $("ul").on("click", "li", function () {
    console.log(this, $(this)[0]) //这两个是一样的
  })
  setTimeout(() => {
    $("ul").append("<li>这是第" + ($("ul").children().length + 1) + "个 li 标签</li>")
  }, 2000);
</script>

⚠️注意: 最后添加的元素也具备同样的点击事件

可以调用on( )为自己绑定事件

<input type="button" value="绑定" id="btn">

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.8.2/jquery.js"></script>
<script>
  $("#btn").on("click", function () {
    console.log("哈哈,我又变帅了")
  })
</script>

live

<body>
  <p>这是一个段落。</p>
  <p>点击任意 p 元素会令其消失。包括本段落。</p>
  <button>在本按钮后面插入新的 p 元素</button>
  <p><b>注释:</b>通过使用 live() 方法而不是 bind() 方法,新的 p 元素同样会在点击时消失。</p>
</body>

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.8.2/jquery.js"></script>

<script type="text/javascript">
  $(document).ready(function () {
    $("p").live("click", function () {
      $(this).slideToggle();
    });
    $("button").click(function () {
      $("<p>This is a new paragraph.</p>").insertAfter("button");
    });
  });
</script>

事件委托的原理

<div></div>

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.8.2/jquery.js"></script>
<script>

  //此时on和delegate的作用是一样的,但是参数的顺序是不一样
  setTimeout(() => {
    $("<p>这是一个p</p>").appendTo($("div"));
  }, 200)

  setTimeout(() => {
    $("<p id='stopPropagation'>这是一个p2</p>").appendTo($("div"));
  }, 500)

  $("div").on("click", "p", function () {
    alert($(this).text())
  });

  setTimeout(() => {
    document.querySelector("#stopPropagation").addEventListener("click", (e) => {
      e.stopPropagation()
    }, true)
  }, 2000);  //2秒后阻止了事件冒泡,所以id=stopPropagation不能再委调父级元素的方法

</script>

事件委托 就是利用冒泡的原理,把事件加到父级上,通过判断事件来源的子集,执行相应的操作,事件委托首先可以极大减少事件绑定次数,提高性能;其次可以让新加入的子元素也可以拥有相同的操作。

事件绑定的区别

方法1: 对象.事件名字(事件处理函数);
方法2: 对象.bind(事件的名字,事件处理函数)
方法1和方法2只能为存在的元素绑定事件,后添加的元素没有事件

下面的两种方式,可以为存在的元素绑定事件,后添加的元素也有事件
对象.delegate("选择器","事件名字",事件处理函数)  //父级元素调用方法,代理子级元素绑定事件
对象.on("事件名字","选择器",事件处理函数) //父级元素调用方法,代理子级元素绑定事件

因为delegate方法中是调用的on的方法
所以,以后直接用on就可以了

解绑事件

unbind()解绑事件

<div>这是div</div>
<input type="button" value="绑定" id="btn1">
<input type="button" value="解绑" id="btn2">


<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.8.2/jquery.js"></script>
<script>
  $("#btn1").click(function () {
    $("div")
      .bind("click", function () {
        console.log("div被点了");
      })
      .bind("click", function () {
        console.log("div点第二个点击");
      })
      .bind("mouseenter", function () {
        $(this).css("backgroundColor", "blue");
      })
      .bind("mouseleave", function () {
        $(this).css("backgroundColor", "yellow");
      })
      .click(function () {
        console.log("哈哈");
      })
  })


  $("#btn2").click(function () {
    // 解绑的是点击事件, 所有的点击事件全部移除
    // $("div").unbind("click");

    //括号中没有任何参数,此时该元素的所有的事件全部解绑
    // $("div").unbind();

    // 同时解绑多个事件
    $('div').unbind("mouseenter mouseleave")
  })

</script>

undelegate() 解绑事件

<div>这是div</div>
<input type="button" value="绑定" id="btn1">
<input type="button" value="解绑" id="btn2">


<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.8.2/jquery.js"></script>
<script>
  $("#btn1").click(function () {
    $("div")
      .click(function () {
        console.log("div被点了")
      })
      .mouseenter(function () {
        console.log("鼠标进来了")
      })
      .mouseleave(function () {
        console.log("鼠标离开了")
      })
      .append($("<p>这是一个p</p>"))  //在div中创建一个p,同时绑定点击事件
      .delegate("p", "click", function () {
        console.log("啊~p被点了")
      })
      .delegate("p", "mouseenter", function () {
        console.log("p的鼠标进入")
      })
  })


  $("#btn2").click(function () {
    //p的点击事件没有了,移除了p的所有的事件
    // $("div").undelegate()

    //移除的是p的点击事件
    $("div").undelegate("p", "click")

    //可以移除多个事件,但是每个事件之间用空格隔开
    // $("div").undelegate("p", "click mouseenter")

    //div所有的事件都没有了
    // $("div").unbind()
  })
</script>

off() 解绑事件

<div>这是div</div>
<input type="button" value="绑定" id="btn1">
<input type="button" value="解绑" id="btn2">


<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.8.2/jquery.js"></script>
<script>
  $("#btn1").click(function () {
    $("div")
      .click(function () {
        console.log("div被点了")
      })
      .mouseenter(function () {
        console.log("鼠标进来了")
      })
      .mouseleave(function () {
        console.log("鼠标离开了")
      })
      .append($("<p>这是一个p</p>"))  //在div中创建一个p,同时绑定点击事件
      .on("click", "p", function () {
        console.log("啊~,p被点了")
      })
      .on("mouseenter", "p", function () {
        console.log("啊~,进入到p里面来了,哦")
      })
      .on("click", "span", function () {
        console.log("哦,span被点了")
      })
  })


  $("#btn2").click(function () {
    //把父级元素和子级元素的点击事件解绑
    //$("div").off("click");

    //父级元素和子级的元素的多个事件,中间用空格
    //$("div").off("click mouseenter");

    //解绑p标签的点击事件
    //$("div").off("click","p");

    //p的两个事件都没了
    //$("div").off("click mouseenter","p");

    //p的所有的事件全部解绑
    //$("div").off("","p");

    //干掉div中所有的子元素的点击事件
    //$("div").off("click","**");

    //父级元素和子级元素的所有的事件全部解绑
     $("div").off();
  })
</script>

<html>
  <body>
    <p>这是一个段落。</p>
    <p>这是另一个段落。</p>
    <p>点击任意 p 元素可以增加尺寸和字间距。包括该段落。</p>
    <button>移除通过 live() 方法为 p 元素添加的 changeSize() 事件处理器</button>
  </body>


  <script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.8.2/jquery.js"></script>
  <script type="text/javascript">
    function changeSize() {
      $(this).animate({ fontSize: "+=3px" });
    }
    function changeColor() {
      $(this).animate({ letterSpacing: "+=2px" });
    }
    $(document).ready(function () {
      $("p").live("click", changeSize);
      $("p").live("click", changeColor);
      $("button").click(function () {
        $("p").die("click", changeSize);
      });
    });
  </script>
</html>

事件解绑的总结

  • 用什么方式绑定事件,最好用对应的方式解绑事件
  • bind括号中写什么事件的名字就会把这个事件解绑,会把这个元素的这个点击的多个事件都会解绑
  • 对象.click()这种方式添加的事件也可以使用 unbind 解绑
  • 括号中没有任何参数,此时该元素的所有的事件全部解绑
  • 同时解绑多个事件 -- 每个事件的名字中间用空格即可

事件冒泡

事件属性

e.target: 这个属性得到的是触发该事件的目标对象,此时是一个DOM对象
e.currentTarget: 这个属性得到的是触发该事件的当前的对象
e.delegateTarget: 这个属性得到的是代理的这个对象

<div>
  <input type="button" value="按钮">
</div>

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.8.2/jquery.js"></script>
<script>
  console.log(window);

  $("div").on("click", "input", function (e) {
    //e.target: 这个属性得到的是触发该事件的目标对象, 此时是一个DOM对象
    //e.currentTarget: 这个属性得到的是触发该事件的当前的对象
    //e.delegateTarget: 这个属性得到的是代理的这个对象
    console.log(e, e.target, e.currentTarget, e.delegateTarget, $(e.currentTarget).attr("id"))
    console.log(e.screenX + "====" + e.screenY)
  })
</script>

阻止事件冒泡

JQ对象中

<input type="button" value="按钮" id="btn">

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.8.2/jquery.js"></script>
<script>
  $("#btn").click(function (event) {
    console.log($(this).attr("id"))

    event.preventDefault()      //阻止表单提交的默认行为 
    event.stopPropagation()
    return false                //直接 return falese
  })
</script>

DOM对象中

<input type="button" value="按钮" id="btn">

<script>
  document.getElementById("btn").onclick = function (e) {
    event.preventDefault()            //阻止默认事件
    e.stopPropagation()               //谷歌 火狐阻止事件冒泡的方法
    window.event.cancelBubble = true  //IE8 阻止事件冒泡的方法
  } 
</script>