事件委托、事件捕获与冒泡(js、vue、react)

JavaScript与HTML的交互是通过事件实现的,事件代表文档流或浏览器窗口中某个有意义的时刻。

       而事件流代表了页面接收事件的顺序,结果IE和Netscape开发团队提出了几乎完全相反的事件流方案,IE将支持事件冒泡流,而Netscape将支持事件捕获流。事件委托、事件捕获与冒泡(js、vue、react)_第1张图片

事件冒泡

       IE提出的事件流叫做事件冒泡,即事件开始时由最具体的元素接收,然后逐级向上传播,看一下以下示例:

<body onclick="bodyclick( )">
   <div onclick="divclick( )">
       <button onclick="buttonclick( )">
       </button>
   </div>
</body>
<script>
function bodyclick(){
    console.log('body被点击')
}
function divclick(){
    console.log('div被点击')
}
function buttonclick(){
    console.log('button被点击')
}
</script>

点击页面上的button:
事件委托、事件捕获与冒泡(js、vue、react)_第2张图片

事件捕获

       网景公司提出的事件流叫事件捕获流。事件捕获流的思想是外层DOM节点应该更早接收到事件,而最具体的节点应该最后接收到事件,针对上面同样的例子,点击按钮,那么此时click事件会按照这样传播:(下面我们就借用addEventListener的第三个参数来模拟事件捕获流

<body>
   <div><button>点击捕获</button></div
</body>
<script>
var body=documemt.querySelector('body')
var div=documemt.querySelector('div')
var button=documemt.querySelector('button')
body.addEventListener('click',function(){console.log('body被点击')},true)
div.addEventListener('click',function(){console.log('div被点击')},true)
button.addEventListener('click',function(){console.log('button被点击')},true)
</script>

打印出来的结果是:
在这里插入图片描述

addEventListener( type, listener, useCapture )简单分析

  • type: 事件类型
  • listener: 事件监听处理函数
  • useCapture: 设置事件查找方式
    false: 冒泡事件(默认值)
    true: 捕获事件

注意:通过addEventListener添加的事件监听必须通过removeEventListener并传入与添加时相同的参数来移除。也就意味着通过addEventListener添加的匿名函数无法移除

vue中的@click

      vue 中@click是默认的冒泡行为,当点击button时,虽然事件流是先捕获后冒泡,当捕获先经过 div时,divClick不触发,所以btnClick先触发,开始冒泡流程到div时,divClick才触发。

<div @click = "divClick">
    <button @click="btnClick">点击</button>
</div>
<script>
var vm = new vue ({
  el:"#app",
  data: {},
  methods: {
    divClick() {
       console.log("divClick")
    },
    btnClick() {
       console.log("btnClick")
    }
  }
})
</script>
// btnClick
// divClick

      vue通过@click.capture事件修饰符改为捕获。

react中的onClick

export class LoginPage extends Component {
    onClickInner(e) {
        console.log('inner a')
    }
    onClickOuter(e) {
        console.log('outer div')
    }
    render() {
        return (
            <div onClick={this.onClickOuter}>
                <a onClick={this.onClickInner}>inner a</a>
            </div>
        )
    }
}

      React中的onClick是冒泡点击事件,同样,使用onClickCapture为dom绑定捕获的点击事件。

事件代理机制(事件委托)

      利用事件冒泡完成事件代理机制:

<ul>
    <li>列表1</li>
    <li>列表2</li>
</ul>

      当我们要给如上列表中的li都绑定一个点击事件点击获取li中的内容,一般是利用for遍历元素绑定点击事件。假如我们有1w个 li 节点,使用如上方式就需要绑定1w个事件,这样操非常影响代码性能。
      此时,我们可以利用冒泡机制来解决如上的问题,就是将事件绑定到父元素身上 ul 身上。

 <body>
    <ul>
        <li>列表1</li>
        <li>列表2</li>
    </ul>
    <script>
        let ul = document.querySelector('ul');
        //我们可以通过事件对象(e)中的target属性可以访问到事件源(也就事件的触发元素)
        ul.addEventListener('click',function(e){
            console.log(e.target.innerHTML);
        },false);
    </script>
</body>

总结:通过上面代码我们知道了事件对象+冒泡机制可以实现事件委托。事件委托就是当事件触发时,通过事件冒泡(或事件捕获)把要做的事委托给父元素来处理。

你可能感兴趣的:(JavaScript,javascript,vue.js,react.js)