Liên kết nhiều sự kiện với người nghe (không có JQuery)?


144

Khi làm việc với các sự kiện trình duyệt, tôi đã bắt đầu kết hợp touchEvents của Safari cho thiết bị di động. Tôi thấy rằng đó addEventListenerlà chồng lên với điều kiện. Dự án này không thể sử dụng JQuery.

Một người nghe sự kiện tiêu chuẩn:

/* option 1 */
window.addEventListener('mousemove', this.mouseMoveHandler, false);
window.addEventListener('touchmove', this.mouseMoveHandler, false);

/* option 2, only enables the required event */
var isTouchEnabled = window.Touch || false;
window.addEventListener(isTouchEnabled ? 'touchmove' : 'mousemove', this.mouseMoveHandler, false);

JQuery bindcho phép nhiều sự kiện, như vậy:

$(window).bind('mousemove touchmove', function(e) {
    //do something;
});

Có cách nào để kết hợp hai trình lắng nghe sự kiện như trong ví dụ JQuery không? Ví dụ:

window.addEventListener('mousemove touchmove', this.mouseMoveHandler, false);

Bất kỳ đề xuất hoặc lời khuyên được đánh giá cao!


@RobG có lẽ vì câu hỏi đang hỏi cách sao chép một số chức năng của jQuery. Tôi không chắc đó có phải là cách sử dụng phù hợp cho thẻ hay không.
Michael Martin-Smucker

Đủ công bằng, dường như với tôi rằng câu hỏi không cần nó. Có vẻ hơi lén lút mặc dù, đã xóa.
RobG

Câu trả lời:


104

Trong POJS, bạn thêm một người nghe cùng một lúc. Việc thêm cùng một người nghe cho hai sự kiện khác nhau trên cùng một phần tử là không phổ biến. Bạn có thể viết hàm nhỏ của riêng bạn để thực hiện công việc, ví dụ:

/* Add one or more listeners to an element
** @param {DOMElement} element - DOM element to add listeners to
** @param {string} eventNames - space separated list of event names, e.g. 'click change'
** @param {Function} listener - function to attach for each event as a listener
*/
function addListenerMulti(element, eventNames, listener) {
  var events = eventNames.split(' ');
  for (var i=0, iLen=events.length; i<iLen; i++) {
    element.addEventListener(events[i], listener, false);
  }
}

addListenerMulti(window, 'mousemove touchmove', function(){…});

Hy vọng nó cho thấy khái niệm.

Chỉnh sửa 2016 / 02-25

Nhận xét của Dalgard khiến tôi phải xem lại điều này. Tôi đoán việc thêm cùng một trình nghe cho nhiều sự kiện trên một phần tử là phổ biến hơn hiện nay để bao gồm các loại giao diện khác nhau được sử dụng và câu trả lời của Isaac cung cấp một cách sử dụng tốt các phương thức được xây dựng trong các phương thức để giảm mã (mặc dù bản thân ít mã hơn , không nhất thiết là một phần thưởng). Mở rộng với các chức năng mũi tên ECMAScript 2015 mang lại:

function addListenerMulti(el, s, fn) {
  s.split(' ').forEach(e => el.addEventListener(e, fn, false));
}

Một chiến lược tương tự có thể thêm cùng một người nghe vào nhiều yếu tố, nhưng nhu cầu thực hiện có thể là một chỉ báo cho sự kiện ủy nhiệm.


4
Cảm ơn bạn vì câu "It is not common to add the same listener for two different events on the same element."Đôi khi các nhà phát triển (xanh hơn) cần nghe điều này để biết họ đang làm đúng :)
Ivan Durst

1
Ý bạn là "nó không phải là UNcommon"?
dampard

2
@ dasmard, điều phổ biến hơn bây giờ là các thiết bị cảm ứng phổ biến hơn, nhưng chỉ dành cho một số sự kiện giới hạn (như mousemove và touchmove). Điều đó được yêu cầu cho thấy sự thiển cận của việc đặt tên các sự kiện sau các mục vật lý, di chuyển con trỏ có thể phù hợp hơn. Nó có thể được thực hiện bằng cảm ứng hoặc thiết bị khác. Trước khi chuột (hoặc chuột) có bánh xe x / y, một số tôi đã sử dụng có bánh xe tay và chân (Stecometer 1970s). Ngoài ra còn có bóng theo dõi và hình cầu, một số di chuyển trong 3d.
RobG

2
@RobG: API tôi đang xử lý là DOM và vâng, thiếu sót của nó là quân đoàn :) Nhưng nó cũng có thể đơn giản là một câu hỏi về việc tránh mã trùng lặp trong trình nghe tương tự.
dunkard

1
@ PedroFerreira, tất nhiên, có lẽ hơn một nửa các trình duyệt hiện đang sử dụng không hỗ trợ các chức năng mũi tên, nhưng chúng rất vui khi chơi và luôn có Babel . ;-)
RobG

119

Một số cú pháp nhỏ gọn đạt được kết quả mong muốn, POJS:

   "mousemove touchmove".split(" ").forEach(function(e){
      window.addEventListener(e,mouseMoveHandler,false);
    });

154
Hoặc trực tiếp['mousemove', 'touchmove'].forEach(...)
Dan Dascalescu

+1 VÀ nó không cần phần mở rộng «chức năng mũi tên ECMAScript 2015»! ;-)
Pedro Ferreira

@zuckerburg Để bắt đầu, thay vì mã hóa mảng bạn đã mã hóa phân tầng và sau đó tách nó ra, bạn có thực sự chắc chắn rằng đây là cách để đi không? Bạn có chắc chắn rằng đây là cách dễ đọc nhất để viết bài này? ['mousemove', 'touchmove'].forEach(function(event) { window.addEventListener(event, handler);}); sẽ không chỉ dễ đọc hơn mà còn nhanh hơn khi không phải phân tách chuỗi và sau đó chạy một hàm cho từng mục trong mảng kết quả.
Iharob Al Asimi

2
@IharobAlAsimi mã này đã được viết cách đây hơn 4 năm, tôi đã tìm thấy phím cách của mình trong thời gian đó. Việc phân tách chuỗi có liên quan đến việc sử dụng chuỗi của OP
Isaac

1
@IharobAlAsimi Tôi không viết mã. Bạn nói nó không thể đọc được. Rõ ràng không phải vì bạn và tôi đều có khả năng đọc mã. Điều này giống như tranh luận về ngữ pháp. 99% tất cả các lập trình viên có thể đọc mã khá độc đáo
zuckerburg

55

Làm sạch câu trả lời của Isaac:

['mousemove', 'touchmove'].forEach(function(e) {
  window.addEventListener(e, mouseMoveHandler);
});

BIÊN TẬP

Chức năng trợ giúp ES6:

function addMultipleEventListener(element, events, handler) {
  events.forEach(e => element.addEventListener(e, handler))
}

1
FYI: map! =
ForEach

10

Cho tôi; mã này hoạt động tốt và là mã ngắn nhất để xử lý nhiều sự kiện có cùng chức năng (nội tuyến).

var eventList = ["change", "keyup", "paste", "input", "propertychange", "..."];
for(event of eventList) {
    element.addEventListener(event, function() {
        // your function body...
        console.log("you inserted things by paste or typing etc.");
    });
}

Chính xác những gì tôi đang tìm kiếm. Cảm ơn!
Elharony

10

ES2015:

let el = document.getElementById("el");
let handler =()=> console.log("changed");
['change', 'keyup', 'cut'].forEach(event => el.addEventListener(event, handler));

Hoặc sử dụng for...ofvòng lặp
anh chàng

3

Tôi có một giải pháp đơn giản hơn cho bạn:

window.onload = window.onresize = (event) => {
    //Your Code Here
}

Tôi đã thử nghiệm điều này, nó hoạt động rất tốt, về mặt tích cực, nó nhỏ gọn và không phức tạp như các ví dụ khác ở đây.


1
Chỉ có một .onload có thể. Có lẽ bạn ghi đè lên một người nghe cũ. Tùy thuộc vào môi trường của bạn, điều này có thể là một vấn đề.
HolgerJeromin

1

AddEventListener lấy một chuỗi đơn giản đại diện cho event.type . Vì vậy, bạn cần phải viết một hàm tùy chỉnh để lặp qua nhiều sự kiện.

Điều này đang được xử lý trong jQuery bằng cách sử dụng .split ("") và sau đó lặp qua danh sách để đặt eventListener cho mỗi types.

    // Add elem as a property of the handle function
    // This is to prevent a memory leak with non-native events in IE.
    eventHandle.elem = elem;

    // Handle multiple events separated by a space
    // jQuery(...).bind("mouseover mouseout", fn);
    types = types.split(" ");  

    var type, i = 0, namespaces;

    while ( (type = types[ i++ ]) ) {  <-- iterates thru 1 by 1

0

Một cách để làm điều đó:

const troll = document.getElementById('troll');

['mousedown', 'mouseup'].forEach(type => {
	if (type === 'mousedown') {
		troll.addEventListener(type, () => console.log('Mouse is down'));
	}
        else if (type === 'mouseup') {
                troll.addEventListener(type, () => console.log('Mouse is up'));
        }
});
img {
  width: 100px;
  cursor: pointer;
}
<div id="troll">
  <img src="http://images.mmorpg.com/features/7909/images/Troll.png" alt="Troll">
</div>

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.