이번에는 웹 개발 시 이벤트 처리규칙과 웹 개발 시 이벤트 처리 시 주의사항에 대해 알려드리겠습니다. 실제 사례를 살펴보겠습니다.
이벤트 처리
이벤트가 트리거되면 이벤트 object(이벤트 개체)가 콜백 매개변수로 이벤트 핸들러에 전달된다는 것을 알고 있습니다. 예:
// 不好的写法function handleClick(event) { var pop = document .getElementById('popup'); popup.style.left = event.clientX + 'px'; popup.style.top = event.clientY + 'px'; popup.className = 'reveal'; }// 你应该明白addListener函数的意思addListener(element, 'click', handleClick);
이 코드는 의 두 가지 속성만 사용합니다. 이벤트 객체: clientX 및 clientY. 페이지에 요소를 표시하기 전에 요소의 위치를 지정하려면 이 두 가지 특성을 사용하세요. 이 코드는 매우 간단하고 문제가 없어 보이지만 이 접근 방식에는 한계가 있으므로 실제로 작성하는 것은 좋지 않은 방법입니다.
규칙 1: 애플리케이션 로직 분리
위 예제 코드의 첫 번째 문제는 이벤트 핸들러에 애플리케이션 로직이 포함되어 있다는 것입니다. 애플리케이션 로직은 사용자 행동이 아닌 애플리케이션과 관련된 기능 코드입니다. 위 예제 코드의 애플리케이션 로직은 특정 위치에 팝업 상자를 표시하는 것입니다. 이러한 상호작용은 사용자가 특정 요소를 클릭할 때 발생해야 하지만 항상 그런 것은 아닙니다.
동일한 로직이 다른 곳에서 트리거될 수 있으므로 모든 이벤트 핸들러에서 애플리케이션 로직을 분리하는 것이 가장 좋습니다. 예를 들어 사용자가 요소 위로 마우스를 이동할 때 팝업 상자를 표시할지, 키보드의 특정 키를 누를 때 동일한 논리적 판단을 내릴지 결정해야 하는 경우가 있습니다. 이러한 방식으로 여러 이벤트 핸들러가 동일한 논리를 실행하지만 코드가 실수로 여러 번 복사됩니다.
이벤트 핸들러에 애플리케이션 로직을 배치할 때의 또 다른 단점은 테스트와 관련이 있습니다. 테스트할 때 요소 클릭을 시뮬레이션하는 대신 함수 코드를 직접 트리거해야 합니다. 애플리케이션 로직이 이벤트 핸들러에 배치된 경우 이를 테스트하는 유일한 방법은 이벤트가 발생하도록 하는 것입니다. 일부 테스트 프레임워크에서는 트리거링 이벤트를 시뮬레이션할 수 있지만 실제로 이는 테스트에 대한 최선의 접근 방식은 아닙니다. 기능 코드를 호출하는 가장 좋은 방법은 단일 함수 호출을 사용하는 것입니다.
항상 애플리케이션 로직과 이벤트 처리 코드를 분리해야 합니다. 이전 예제 코드를 리팩터링하려는 경우 첫 번째 단계는 팝업 상자 논리를 처리하는 코드를 별도의 함수에 넣는 것입니다. 이 함수는 애플리케이션에 정의된 전역 개체에 탑재될 가능성이 높습니다. 이벤트 핸들러는 항상 동일한 전역 개체에 있어야 하므로 두 가지 메서드가 있습니다.
// 好的写法 - 拆分应用逻辑var MyApplication = { handleClick: function (event) { this.showPopup(event); }, showPopup: function (event) { var pop = document.getElementById('popup'); popup.style.left = event.clientX + 'px'; popup.style.top = event.clientY + 'px'; popup.className = 'reveal'; } }; addListener(element, 'click', function (event) { MyApplication.handleClick(event); });
이전에는 이벤트 핸들러에 포함되었던 모든 애플리케이션 로직이 이제 MyApplication.showPopup() 메서드로 이동되었습니다. 이제 MyApplication.handleClick() 메서드는 MyApplication.showPopup()을 호출하는 한 가지 작업만 수행합니다. 애플리케이션 로직이 제거되면 동일한 기능 코드에 대한 호출이 여러 지점에서 발생할 수 있으며 특정 이벤트의 트리거링에 의존할 필요가 없으므로 확실히 더 편리합니다. 그러나 이는 이벤트 핸들러 코드를 분석하는 첫 번째 단계일 뿐입니다.
Rule 2: 이벤트 객체를 배포하지 마세요
애플리케이션 로직을 제거한 후에도 위의 예제 코드에는 여전히 문제가 있습니다. 즉, 이벤트 객체가 통제할 수 없게 배포된다는 것입니다. 익명 이벤트 핸들러에서 MyApplication.handleClick()을 전달한 다음 이를 MyApplication.showPopup()에 전달합니다. 위에서 언급했듯이 이벤트 객체에는 이벤트와 관련된 추가 정보가 많이 포함되어 있으며, 이 코드에서는 그 중 두 가지만 사용합니다. 애플리케이션 로직은 다음과 같은 이유로 기능을 올바르게 완료하기 위해 이벤트 객체에 의존해서는 안 됩니다.
메서드 인터페이스는 어떤 데이터가 필요한지 나타내지 않습니다. 좋은 API는 기대치와 종속성에 대해 투명해야 합니다. 이벤트 객체를 매개변수로 취한다고 해서 이벤트의 어떤 속성이 유용하고 무엇에 사용되는지 알 수는 없습니다.
그러면 이 방법을 테스트하려면 이벤트 객체를 다시 생성하여 매개변수로 전달해야 합니다. . 따라서 이 메소드가 어떤 정보를 사용하는지 정확히 알아야 테스트 코드를 올바르게 작성할 수 있습니다.
이러한 문제(불분명한 인터페이스 형식 및 테스트를 위해 자체 생성된 이벤트 개체 참조)는 대규모 웹 응용 프로그램에서는 권장되지 않습니다. 코드의 명확성이 부족하면 버그가 발생할 수 있습니다.
가장 좋은 방법은 이벤트 핸들러가 이벤트 개체를 사용하여 이벤트를 처리하도록 한 다음 필요한 모든 데이터를 가져와 애플리케이션 로직에 전달하는 것입니다. 예를 들어 MyApplication.showPopup() 메서드에는 x 좌표와 y 좌표라는 두 가지 데이터만 필요합니다. 이러한 방식으로 이 두 매개변수를 수신하도록 메소드를 다시 작성합니다.
// 好的写法var MyApplication = { handleClick: function (event) { this.showPopup(event.clientX, event.clientY); }, showPopup: function (x, y) { var pop = document.getElementById('popup'); popup.style.left = x + 'px'; popup.style.top = y + 'px'; popup.className = 'reveal'; } }; addListener(element, 'click', function (event) { MyApplication.handleClick(event); });
在这段新重写的代码中,MyApplication.handleClick()将x坐标和y坐标传入了MyApplication.showPopup(),代替了之前传入的事件对象。可以很清晰地看到MyApplication.showPopup()所期望传入的参数,并且在测试或代码的任意位置都可以很轻易地直接调用这段逻辑,比如:
// 这样调用非常棒MyApplication.showPopup(10, 10);
当处理事件时,最好让事件处理程序成为接触到event对象的唯一的函数。事件处理程序应当在进入应用逻辑之前针对event对象执行任何必要的操作,包括阻止默认事件或阻止事件冒泡,都应当直接包含在事件处理程序中。比如:
// 好的写法var MyApplication = { handleClick: function (event) { // 假设事件支持DOM Level2 event.preventDefault(); event.stopPropagation(); // 传入应用逻辑 this.showPopup(event.clientX, event.clientY); }, showPopup: function (x, y) { var pop = document.getElementById('popup'); popup.style.left = x + 'px'; popup.style.top = y + 'px'; popup.className = 'reveal'; } }; addListener(element, 'click', function (event) { MyApplication.handleClick(event); });
在这段代码中,MyApplication.handleClick()是事件处理程序,因此它在将数据传入应用逻辑之前调用了event.preventDefault()和event.stopPropagation(),这清除地展示了事件处理程序和应用逻辑之间的分工。因为应用逻辑不需要对event产生依赖,进而在很多地方都可以轻松地使用相同的业务逻辑,包括写测试代码。
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
위 내용은 웹 개발에서 이벤트 처리 규칙은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!