[javascript] onclick () 및 onblur () 주문 문제

사용자 지정 드롭 다운 메뉴를 표시하는 입력 필드가 있습니다. 다음 기능을 원합니다.

  • 사용자가 입력 필드 외부의 아무 곳이나 클릭하면 메뉴가 제거되어야합니다.
  • 보다 구체적으로 사용자가 메뉴 내의 div를 클릭하면 메뉴를 제거 하고 어떤 div를 클릭했는지에 따라 특별한 처리가 수행되어야합니다.

내 구현은 다음과 같습니다.

입력 필드에는 사용자가 입력 필드 외부를 클릭 할 때마다 onblur()메뉴를 삭제 하는 이벤트가 있습니다 (상위 항목 innerHTML을 빈 문자열로 설정). 메뉴 내부의 div onclick()에는 특수 처리를 실행하는 이벤트 도 있습니다 .

문제는 onclick()메뉴를 클릭 할 때 이벤트가 실행되지 않는다는 것입니다. 입력 필드 onblur()가 먼저 실행되고 onclick()s!

메뉴 div ‘ onclick()onmousedown()onmouseup()이벤트 로 나누고이 답변 에서 제안 된 것과 유사하게 마우스를 위로하면 마우스를 내리는 전역 플래그를 설정 하여 문제를 해결했습니다 . onmousedown()이전 onblur()에 실행되기 때문에 onblur()메뉴 div 중 하나를 클릭하면 플래그가 설정 되지만 화면의 다른 곳이 클릭 된 경우에는 설정되지 않습니다. 메뉴를 클릭하면 메뉴 onblur()를 삭제하지 않고 즉시 돌아온 다음가 onclick()실행될 때까지 기다리면 메뉴 를 안전하게 삭제할 수 있습니다.

더 우아한 해결책이 있습니까?

코드는 다음과 같습니다.

<div class="menu" onmousedown="setFlag()" onmouseup="doProcessing()">...</div>
<input id="input" onblur="removeMenu()" ... />

var mouseflag;

function setFlag() {
    mouseflag = true;
}

function removeMenu() {
    if (!mouseflag) {
        document.getElementById('menu').innerHTML = '';
    }
}

function doProcessing(id, name) {
    mouseflag = false;
    ...
}



답변

나는 당신과 똑같은 문제를 겪고 있었는데, 내 UI는 당신이 설명하는 것과 똑같이 디자인되었습니다. 나는 단순히 onClick메뉴 항목을 onMouseDown. 나는 아무것도하지 않았다. 아니요 onMouseUp, 플래그가 없습니다. 이렇게하면 추가 작업없이 브라우저가 이러한 이벤트 처리기의 우선 순위에 따라 자동으로 다시 정렬되도록하여 문제가 해결되었습니다.

이것이 당신에게도 효과가 없었을 이유가 있습니까?


답변

onClick로 바꾸면 안됩니다 onMouseDown.

이 접근 방식은 다소 효과가 있지만 두 가지 이벤트는 사용자의 눈에 서로 다른 기대치를 갖는 근본적으로 다른 이벤트입니다. onMouseDown대신 사용하면 onClick이 경우 소프트웨어의 예측 가능성이 손상됩니다. 따라서 두 이벤트는 서로 바꿔서 사용할 수 없습니다.

예를 들어, 실수로 버튼을 클릭 할 때 사용자는 마우스 클릭을 누른 상태에서 커서를 요소 외부로 끌고 마우스 버튼을 놓아서 결과적으로 아무 동작도하지 않을 것으로 예상합니다. onClick이렇게합니다. onMouseDown사용자가 마우스를 누르고있는 것을 허용하지 않고 대신 사용자에 대한 의지없이 즉시 작업을 트리거합니다. onClick컴퓨터에서 작업을 트리거 할 것으로 예상되는 표준입니다.

이 상황 event.preventDefault()에서 onMouseDown이벤트를 요청 하십시오 . onMouseDown기본적으로 흐림 이벤트를 발생시키고를 preventDefault호출 할 때 발생하지 않습니다 . 그런 다음 부를 onClick기회가 있습니다. 흐림 이벤트는 onClick.

결국 onClick이벤트는 동일한 요소 내에서 둘 다 발생하는 경우에만 onMouseDown및 의 조합입니다 onMouseUp.


답변

에 교체 onmousedownonfocus. 따라서이 이벤트는 포커스가 텍스트 상자 안에있을 때 트리거됩니다.

에 교체 onmouseuponblur. 텍스트 상자에서 포커스를 빼는 순간 onblur가 실행됩니다.

나는 이것이 당신이 필요로 할 것이라고 생각합니다.

업데이트 :

onfocus 함수를 실행할 때-> onblur에서 적용 할 클래스를 제거하고 onfocus에서 실행하려는 클래스를 추가합니다.

onblur 함수를 실행할 때-> onfocus에서 적용 할 클래스를 제거하고 onblur에서 실행하려는 클래스를 추가합니다.

플래그 변수가 필요하지 않습니다.

업데이트 2 :

onmouseout 및 onmouseover 이벤트를 사용할 수 있습니다.

onmouseover- 커서가 그 위에있을 때 감지합니다.

onmouseout- 커서가 떠날 때 감지합니다.


답변

보다 우아한 (하지만 성능이 떨어지는) 솔루션 :

대신 메뉴 사용을 제거하기 위해 입력의 위해 onblur를 사용 document.onclick후 화재, onblur.

그러나 이것은 또한 입력 자체를 클릭 할 때 메뉴가 제거됨을 의미하며 이는 바람직하지 않은 동작입니다. 문서 클릭 이벤트에 클릭이 전파되지 않도록하려면 input.onclickwith event.stopPropagation()를 설정 하십시오.


답변

onfocus로 onclick 변경

onblur와 onclick이 잘 어울리지 않더라도 분명히 onfocus와 yes onblur입니다. 메뉴가 닫힌 후에도 onfocus는 내부를 클릭 한 요소에 대해 여전히 유효하기 때문입니다.

나는했고 효과가 있었다.


답변

다음 과 같이 핸들러 setInterval내부 에서 함수 를 사용할 수 있습니다 onBlur.

<input id="input" onblur="removeMenu()" ... />

function removeMenu() {
    setInterval(function(){
        if (!mouseflag) {
            document.getElementById('menu').innerHTML = '';
        }
    }, 0);
}

setInterval함수는 onBlur 호출 스택에서 함수를 제거합니다. 시간을 0으로 설정했기 때문에이 함수는 다른 이벤트 핸들러가 완료된 직후에 호출됩니다.


답변