>  기사  >  웹 프론트엔드  >  프런트 엔드에서 이벤트 전파를 방지하는 방법

프런트 엔드에서 이벤트 전파를 방지하는 방법

php中世界最好的语言
php中世界最好的语言원래의
2018-05-24 11:01:421781검색

이번에는 프런트엔드에서 이벤트 확산을 방지하는 방법을 알려드리겠습니다. 프런트엔드에서 이벤트 확산을 방지하기 위한 주의사항은 무엇인가요? 실제 사례를 살펴보겠습니다.

작은 데모를 만들고, 버튼을 클릭하여 플로팅 레이어를 표시하고, 다른 곳을 클릭하여 플로팅 레이어를 닫고, 간단한 CSS를 작성하세요.

<style>
.wrapper{
    position:relative;
    display:inline-block;
}
.popover{
    position:absolute;
    border:1px solid red;
    left:100%;
    top:0;
    padding:10px;
    margin-left:10px;
    background:white;
    display: none;  /*默认隐藏*/
}
.popover::before{
    position:absolute;
    content:'';
    top:5px;
    right:100%;
    border:10px solid transparent;
    border-right-color:red;
}
.popover::after{
    position:absolute;
    content:'';
    top:5px;
    right:100%;
    border:10px solid transparent;
    border-right-color:white;
    margin-right:-1px;
}

</style>
<p id="wrapper" class=&#39;wrapper&#39;>
    <button id="clickMe">点我</button>
    <p id="popover" class="popover">
        <input type="checkbox">浮层
    </p>
</p>
<script>
    clickMe.addEventListener('click',function(){
        popover.style.display = 'block';
    });
</script>

이제 페이지의 빈 공간을 클릭하여 닫으면 어떻게 될까요? 어떤 방법을 써야 할까요? 아래 코드처럼 문서 모니터링을 생각하면 쉽죠

document.addEventListener('click',function(){
    popover.stely.display = 'none';
});

그런데 실제로 이렇게 작성하고 나면 버튼이 무효가 되고 어떻게 눌러도 반응이 없습니다. 왜 이런가요?
이전 글에서 언급한 캡처 및 버블링 이벤트를 이해하고 나면 []()를 쉽게 이해할 수 있습니다.
모니터링이 캡처 단계인지 버블링 단계인지 지정하지 않았습니다. 브라우저는 기본적으로 버블링 단계로 설정되어 있습니다. 버튼을 클릭하면 캡처 단계가 발생하지 않지만 먼저 버튼이 다릅니다. 코드의 함수>가 먼저 실행된 다음 <code>문서의 함수도 실행되어 플로팅 레이어가 다시 숨겨진 것처럼 보입니다. button上函数先触发,然后document上函数也触发了,导致准备出现的浮层又被隐藏了。
那你可能要问,button上的事件执行了没?其实这两个事件都执行了,只是时间太短,浏览器默认一起执行了,可以在里面加一个debugger,就可以看到了。

clickMe.addEventListener('click',function(){
    popover.style.display = 'block';
});

那该怎么解决呢?最简单的方法是,除了要执行popover.style.display = 'block',还要阻止事件传播

clickMe.addEventlistener('click',function(){
    popover.style.display = 'block';
});

popover.addEventListener('click',function(e){
    e.stopPropagation();
});

这里为什么添加在按钮的父元素上面呢?如果不添加在父元素上面,点击浮层的时候,浮层也会被关闭。

如果页面上有很多监听器的话,这个方法是比较浪费内存的,比较省内存的方法用JQuery 做

$(clickMe).on('click',function(){
    $(popover).show();
    $(document).one('click',function(){
        $(popover).hide();
    });
});
$(wrapper).on('click',function(e){
    e.stopPropagation();    
})

一开始不监听,只在popover`show`的时候监听一次,马上关掉,这叫做清理战场。
$(wrapper).on('click',false) 和下面的代码完全等价

$(wrapper).on('click',function(e){
    e.preventDefault();     //阻止默认事件
    e.stopPropagation();    //阻止传播
})

但是如果页面中有checkbox,你在它的父元素任何一层,包括checkbox自己,添加了组织默认事件那么这个checkbox就没办法被check

这里有个问题,如果没有阻止事件传播,向下面这样,会发生什么事情呢?

$(clickMe).on('click',function(){
    $(popover).show();
    $(document).one('click',funtion(){
        $(popover).hide();
    });
});

当然了,和之前一样,什么事情也不会发生,那当我点击按钮之后里面都发生了那些事情呢?
当我点击了按钮之后,它会做两件事情,首先把popover`show出来,然后把hide函数添加到document上面,当事件传播到document`,就会又把它给隐藏了。

可以给它添加一个setTimeout()函数来解决这个问题

$(clickMe).on('click',function(){
    $(popover).show();
    setTimeout(function(){
        $(document).one('click',function(){
            $(popover).hide();
        })
    },0)
});

setTimeout(fn,0)这个0不是马上执行,而是尽快执行,具体是在冒泡结束在执行这里的函数,也就是说,当冒泡结束后,在把监听事件添加到document上面,等待用户下次点击在执行。

总结:

  1. 同时监听buttondocument,点啥都没反应,因为两个函数都执行了,用阻止事件传播解决了,比较浪费内存

  2. 好一定的方法是用jQuery 做,点击button后在监听document,关闭了就不再监听,不阻止事件传播,点啥也没反应,两种解决方法:一种是阻止事件传播,另一种是添加一个setTimeout()그렇다면 버튼의 이벤트가 실행되었나요? 실제로는 두 이벤트가 모두 실행되는데 시간이 너무 짧습니다. 브라우저에서는 기본적으로 함께 실행합니다. 내부에 디버거를 추가하면 볼 수 있습니다.

    rrreee
  3. 그럼 어떻게 해결하나요? 가장 간단한 방법은 popover.style.display = 'block'을 실행하는 것 외에도 이벤트가 전파되는 것을 방지하는 것입니다
rrreee

여기서 버튼의 상위 요소에 추가되는 이유는 무엇인가요? 상위 요소에 추가되지 않은 경우 플로팅 레이어를 클릭하면 닫힙니다.

페이지에 리스너가 많은 경우 이 방법은 메모리 낭비입니다. 메모리를 더 절약하는 방법은 JQuery를 사용하는 것입니다.

rrreee

처음에는 수신하지 않고 popover`show 때만 수신합니다. ` 한 번 모니터링하고 즉시 끄는 것을 전장 청소라고 합니다. $(wrapper).on('click',false)는 다음 코드와 완전히 동일합니다. rrreee
그러나 페이지에 체크박스가 있으면 체크박스 자체를 포함한 요소의 레이어가 조직 기본 이벤트를 추가하는 경우 이 체크박스체크될 수 없습니다.

여기서 궁금한 점이 있습니다. 이벤트 확산을 막지 못하면 아래와 같이 어떻게 되나요? rrreee물론 이전처럼 아무 일도 일어나지 않을 텐데 버튼을 눌렀을 때 무슨 일이 일어났나요?
버튼을 클릭하면 먼저 popover`show가 나오고 hide 기능이 에 추가됩니다. >document 위에서 이벤트가 document`로 전파되면 다시 숨겨집니다.

setTimeout() 함수를 추가하면 이 문제를 해결할 수 있습니다rrreeesetTimeout(fn,0)0은(는) 그렇지 않습니다. 즉, 버블링이 끝나면 청취 이벤트를 document에 추가하고 기다립니다. 사용자는 다음 번에 구현을 클릭해야 합니다.

요약:

  1. 버튼문서를 동시에 모니터링하면 클릭해도 아무 일도 일어나지 않습니다. , 왜냐하면 둘 다 함수가 모두 실행되고 메모리 낭비인 이벤트 전파를 방지하여 문제가 해결되기 때문입니다🎜🎜
  2. 🎜제이쿼리를 사용하는 것이 가장 좋은 방법은 버튼을 클릭한 다음 document 를 들어보세요. 꺼져 있으면 더 이상 듣지 않고, 이벤트 전파를 막지 않으며, 클릭해도 아무 일도 일어나지 않습니다. 두 가지 해결 방법이 있습니다. 하나는 방지하는 것입니다. 이벤트 전파와 다른 하나는 setTimeout() 함수를 추가하는 것입니다. 🎜🎜🎜🎜이 기사의 사례를 읽으신 후 방법을 마스터하셨다고 생각합니다. 더 흥미로운 정보를 보려면 PHP 중국어 웹사이트의 다른 관련 기사를 주목하세요! 🎜🎜추천 도서: 🎜🎜🎜React-router v4 사용 단계에 대한 자세한 설명🎜🎜🎜🎜🎜Chart.js 경량 차트 라이브러리 사용 사례 분석🎜🎜🎜🎜🎜Chart.js 경량 차트 사용 단계에 대한 자세한 설명 HTML5 차트 그리기 도구 라이브러리 🎜🎜🎜🎜🎜

위 내용은 프런트 엔드에서 이벤트 전파를 방지하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.