auxclick sắp có trên Chrome 55

Jeff Posnick
J Jeff Posnick

Khi nào một lượt nhấp không phải là click? Đối với nhà phát triển web làm việc trên giao diện người dùng phức tạp, đó không phải là một câu hỏi triết học trừu tượng. Nếu đang triển khai hành vi nhập bằng chuột tuỳ chỉnh, bạn phải lưu ý đến ý định của người dùng. Ví dụ: nếu người dùng nhấp vào một đường liên kết bằng nút giữa trên chuột, thì họ nên mở một thẻ mới chứa nội dung của đường liên kết đó. Nếu người dùng nhấp giữa vào một thành phần ngẫu nhiên trên giao diện người dùng, thì bạn nên giả định rằng đó là do vô tình và bỏ qua hoạt động đầu vào đó, trong khi một lượt nhấp vào nút chính sẽ kích hoạt phản hồi từ giao diện người dùng.

Nếu hơi cồng kềnh, bạn có thể mô hình hoá các hoạt động tương tác có sắc thái này thông qua một trình nghe sự kiện click. Bạn sẽ phải kiểm tra rõ ràng thuộc tính button của MouseEvent để xem thuộc tính này có được đặt thành 0 hay không, đại diện cho nút chính, hay bất kỳ thành phần nào khác, trong đó 1 thường đại diện cho nút ở giữa, v.v. Tuy nhiên, không có nhiều nhà phát triển chọn kiểm tra rõ ràng thuộc tính button, dẫn đến mã xử lý tất cả các click theo cách giống nhau, bất kể bạn nhấn nút nào.

Kể từ Chrome 55, một loại MouseEvent mới có tên là auxclick sẽ được kích hoạt để phản hồi mọi lượt nhấp được thực hiện bằng nút phụ. Sự kiện mới này đi kèm với sự thay đổi tương ứng về hành vi của sự kiện click: sự kiện này sẽ chỉ kích hoạt khi nhấn nút chuột chính. Chúng tôi hy vọng những thay đổi này sẽ giúp các nhà phát triển web dễ dàng viết các trình xử lý sự kiện chỉ phản hồi loại lượt nhấp mà họ quan tâm mà không cần phải kiểm tra cụ thể thuộc tính MouseEvent.button.

Giảm dương tính giả

Như đã đề cập, một động lực để tạo auxclick là để tránh triển khai các trình xử lý click tuỳ chỉnh ghi đè nhầm hành vi "middle-click-opens-a-tab". Ví dụ: hãy tưởng tượng rằng bạn đã viết một trình xử lý sự kiện click sử dụng API lịch sử để ghi lại thanh vị trí và triển khai các thao tác điều hướng trên một trang tuỳ chỉnh. Mã này có thể trông giống như sau:

document.querySelector('#my-link').addEventListener('click', event => {
    event.preventDefault();
    // ...call history.pushState(), use client-side rendering, etc....
});

Logic tuỳ chỉnh có thể hoạt động như dự kiến khi được kích hoạt bởi nút chính trên chuột, nhưng nếu mã đó chạy khi nhấp vào nút giữa thì đó thực sự là dương tính giả. Trước hành vi mới, bạn sẽ ngăn thao tác mặc định là mở thẻ mới (điều này đi ngược lại kỳ vọng của người dùng). Mặc dù bạn có thể kiểm tra rõ ràng event.button === 0 khi bắt đầu trình xử lý và chỉ thực thi mã trong trường hợp đó, nhưng bạn sẽ dễ bị quên hoặc không bao giờ nhận ra mình cần làm điều đó.

Chỉ chạy mã bạn cần

Mặt khác của việc có ít cảnh báo nhầm hơn là các lệnh gọi lại auxclick sẽ chỉ chạy khi thực sự có một nút chuột không phải là chính được nhấp vào. Chẳng hạn, nếu có mã cần tính toán URL đích thích hợp trước khi mở thẻ mới, bạn có thể theo dõi auxclick và đưa logic đó vào lệnh gọi lại. Việc này sẽ không làm phát sinh chi phí chạy khi nhấp vào nút chuột chính.

Khả năng hỗ trợ và khả năng tương thích của trình duyệt

Hành vi mới này hiện chỉ được triển khai trong Chrome 55. Như đã đề cập trong đề xuất ban đầu, chúng tôi coi trọng ý kiến phản hồi (cả tích cực và tiêu cực) của cộng đồng nhà phát triển web. Gửi vấn đề trên GitHub là cách tốt nhất để chia sẻ ý kiến phản hồi đó với những người đang xây dựng quy trình chuẩn hoá.

Trong thời gian chờ đợi, các nhà phát triển không cần phải đợi auxclick được cung cấp rộng rãi để làm theo một số phương pháp hay nhất trong việc xử lý các sự kiện chuột. Nếu dành thời gian để kiểm tra giá trị của thuộc tính MouseEvent.button khi bắt đầu trình xử lý sự kiện click, bạn có thể đảm bảo rằng mình thực hiện hành động thích hợp. Mẫu sau đây sẽ xử lý các lượt nhấp chính và phụ theo cách khác nhau, dù có hỗ trợ gốc cho auxclick hay không:

function handlePrimaryClick(event) {
    // ...code to handle the primary button click...
}

function handleAuxClick(event) {
    // ...code to handle the auxiliary button click….
}

document.querySelector('#my-link').addEventListener('click', event => {
    if (event.button === 0) {
    return handlePrimaryClick(event);
    }


    // This provides fallback behavior in browsers without auxclick.
    return handleAuxClick(event);
});

// Explicitly listen for auxclick in browsers that support it.
document.querySelector('#my-link').addEventListener('auxclick', handleAuxClick);