Làm cách nào để ngăn trang web cuộn lên đầu trang khi nhấp vào liên kết kích hoạt JavaScript?


135

Khi tôi có một liên kết được nối dây với một sự kiện jQuery hoặc JavaScript, chẳng hạn như:

<a href="#">My Link</a>

Làm cách nào để ngăn trang cuộn lên trên cùng? Khi tôi xóa thuộc tính href khỏi neo, trang không cuộn lên trên cùng nhưng liên kết dường như không thể nhấp được.

Câu trả lời:


197

Bạn cần ngăn hành động mặc định cho sự kiện nhấp (nghĩa là điều hướng đến mục tiêu liên kết) xảy ra.

Có hai cách để làm điều này.

Lựa chọn 1: event.preventDefault()

Gọi .preventDefault()phương thức của đối tượng sự kiện được chuyển đến bộ xử lý của bạn. Nếu bạn đang sử dụng jQuery để liên kết các trình xử lý của mình, sự kiện đó sẽ là một phiên bản jQuery.Eventvà đó sẽ là phiên bản jQuery của .preventDefault(). Nếu bạn đang sử dụng addEventListenerđể ràng buộc trình xử lý của mình, nó sẽ là Eventphiên bản DOM thô và .preventDefault(). Dù bằng cách nào cũng sẽ làm những gì bạn cần.

Ví dụ:

$('#ma_link').click(function($e) {
    $e.preventDefault();
    doSomething();
});

document.getElementById('#ma_link').addEventListener('click', function (e) {
    e.preventDefault();
    doSomething();
})

Lựa chọn 2: return false;

Trong jQuery :

Trả về false từ trình xử lý sự kiện sẽ tự động gọi event.stopPropagation () và event.preventDefault ()

Vì vậy, với jQuery, bạn có thể sử dụng cách tiếp cận này để ngăn chặn hành vi liên kết mặc định:

$('#ma_link').click(function(e) {
     doSomething();
     return false;
});

Nếu bạn đang sử dụng các sự kiện DOM thô, điều này cũng sẽ hoạt động trên các trình duyệt hiện đại, vì đặc tả HTML 5 chỉ ra hành vi này. Tuy nhiên, các phiên bản cũ hơn của thông số kỹ thuật thì không, vì vậy nếu bạn cần khả năng tương thích tối đa với các trình duyệt cũ hơn, bạn nên gọi .preventDefault()một cách rõ ràng. Xem event.preventDefault () so với return false (không có jQuery) để biết chi tiết cụ thể.


9
Đã đăng một giải pháp (trễ 3 năm) mà không yêu cầu đính kèm trình xử lý nhấp chuột: stackoverflow.com/a/11246131/216941
Matt Crinklaw-Vogt

Trong trường hợp này, Achilles chỉ đang làm điều này bởi vì anh ta muốn liên kết xuất hiện dưới dạng có thể nhấp, mà anh ta không cần phải sử dụng href = "#". Xem câu trả lời của tôi để biết thêm.
achecopar

164

Bạn có thể đặt href của bạn thành #!thay vì#

Ví dụ,

<a href="#!">Link</a>

sẽ không thực hiện bất kỳ cuộn khi nhấp vào.

Coi chừng! Điều này vẫn sẽ thêm một mục vào lịch sử của trình duyệt khi được nhấp, nghĩa là sau khi nhấp vào liên kết của bạn, nút quay lại của người dùng sẽ không đưa họ đến trang mà họ đã truy cập trước đó. Vì lý do này, có lẽ tốt hơn là sử dụng .preventDefault()phương pháp này hoặc sử dụng cả hai kết hợp.

Dưới đây là một Fiddle minh họa điều này (chỉ cần xóa trình duyệt của bạn xuống cho đến khi bạn nhận được một thanh cuộn):
http://jsfiddle.net/9dEG7/


Đối với các mọt sách đặc tả - tại sao điều này hoạt động:

Hành vi này được chỉ định trong thông số HTML5 trong phần Điều hướng đến phần định danh phân đoạn. Lý do khiến một liên kết với a href "#"khiến tài liệu cuộn lên trên cùng là vì hành vi này được chỉ định rõ ràng là cách để xử lý một định danh phân đoạn trống:

2. Nếu fragidlà chuỗi trống, thì phần được chỉ định của tài liệu là phần trên cùng của tài liệu

Sử dụng a href "#!"thay vì hoạt động đơn giản vì nó tránh được quy tắc này. Không có gì kỳ diệu về dấu chấm than - nó chỉ tạo ra một định danh phân đoạn thuận tiện bởi vì nó khác biệt đáng kể với một mảnh vỡ điển hình và không bao giờ khớp với idhoặc namemột yếu tố trên trang của bạn. Thật vậy, chúng ta có thể đặt hầu hết mọi thứ sau hàm băm; các mảnh duy nhất không đủ là chuỗi trống, từ 'trên cùng' hoặc chuỗi khớp với namehoặc idthuộc tính của các thành phần trên trang.

Chính xác hơn, chúng ta chỉ cần một mã định danh phân đoạn sẽ khiến chúng ta rơi vào bước 8 trong thuật toán sau để xác định phần được chỉ định của tài liệu từ mảnh:

  1. Áp dụng các thuật toán phân tích cú pháp URL đến URL, và để cho fragid là thành phần mảnh của URL phân tích cú pháp kết quả.

  2. Nếu fragidlà chuỗi rỗng, thì phần được chỉ định của tài liệu là phần trên cùng của tài liệu; dừng thuật toán ở đây

  3. Hãy fragid byteslà kết quả của việc giải mã phần trăm fragid.

  4. Hãy decoded fragidlà kết quả của việc áp dụng thuật toán giải mã UTF-8 cho fragid bytes. Nếu bộ giải mã UTF-8 phát ra lỗi bộ giải mã, hãy hủy bỏ bộ giải mã và thay vào đó nhảy đến bước được gắn nhãn no decoded fragid.

  5. Nếu có một phần tử trong DOM có ID chính xác bằng decoded fragid, thì phần tử đầu tiên theo thứ tự cây là phần được chỉ định của tài liệu; dừng thuật toán ở đây

  6. Không được giải mã dễ vỡ : Nếu có một phần tử trong DOM có thuộc tính name có giá trị chính xác bằng fragid( khôngdecoded fragid ), thì phần tử đầu tiên theo thứ tự cây là phần được chỉ định của tài liệu; dừng thuật toán ở đây

  7. Nếu Fragid là một trường hợp không nhạy cảm trường hợp ASCII cho chuỗi top, thì phần được chỉ định của tài liệu là phần trên cùng của tài liệu; dừng thuật toán ở đây

  8. Mặt khác, không có phần nào được chỉ định trong tài liệu.

Miễn là chúng tôi đạt được bước 8 và không có phần nào được chỉ định trong tài liệu , quy tắc sau sẽ có hiệu lực:

Nếu không có phần được chỉ định ... thì tác nhân người dùng phải không làm gì cả.

đó là lý do tại sao trình duyệt không cuộn.


4
Không quan trọng nếu bạn đặt '!' hoặc bất kỳ giá trị nào khác, miễn là id không phải là một phần của DOM.
Gopinath

3
Sau khi trở thành người ủng hộ phương pháp này, tôi đã thực hiện 180 và khuyên chống lại nó. Chú ý: các liên kết như thế này vẫn sẽ thay đổi URL trang, dẫn đến một mục nhập thêm trong lịch sử của trình duyệt và khiến nút "quay lại" chỉ đơn giản là xóa đoạn khỏi URL thay vì làm những gì người dùng mong đợi. Do đó, giải pháp này tự nó, trong khi trả lời câu hỏi khi được hỏi, thường không phải là một giải pháp thay thế mong muốn để sử dụng preventDefault()trong trình xử lý nhấp chuột - khá đáng buồn.
Mark Amery

1
Tại sao không sử dụng href = "javascript:;" thay thế? Theo tôi biết nó sẽ không thay đổi lịch sử của trình duyệt. Đăng về nó trên câu trả lời của tôi.
achecopar

30

Một cách tiếp cận dễ dàng là tận dụng mã này:

<a href="javascript:void(0);">Link Title</a>

Cách tiếp cận này không bắt buộc phải làm mới trang, vì vậy thanh cuộn vẫn giữ nguyên vị trí. Ngoài ra, nó cho phép bạn lập trình thay đổi sự kiện onclick và xử lý ràng buộc sự kiện phía máy khách bằng jQuery.

Vì những lý do này, giải pháp trên tốt hơn:

<a href="javascript:myClickHandler();">Link Title</a>
<a href="#" onclick="myClickHandler(); return false;">Link Title</a>

trong đó giải pháp cuối cùng sẽ tránh được sự cố cuộn-cuộn khi và chỉ khi phương thức myClickHandler không thành công.


12

Trả về false từ mã bạn đang gọi sẽ hoạt động và trong một số trường hợp là phương thức ưa thích nhưng bạn cũng có thể vì vậy

<a href="javascript:;">Link Title</a>

Khi nói đến SEO, nó thực sự phụ thuộc vào liên kết của bạn sẽ được sử dụng cho mục đích gì. Nếu bạn thực sự sử dụng nó để liên kết đến một số nội dung khác thì tôi đồng ý lý tưởng là bạn sẽ muốn một cái gì đó có ý nghĩa ở đây nhưng nếu bạn đang sử dụng liên kết cho các mục đích chức năng thì có thể như Stack Overflow làm cho thanh công cụ bài viết (đậm, in nghiêng, siêu liên kết , v.v.) thì có lẽ không vấn đề gì.


9

Bạn nên thay đổi

<a href="#">My Link</a>

đến

<a href="javascript:;">My Link</a>

Bằng cách này khi nhấp vào liên kết, trang sẽ không cuộn lên đầu. Điều này sạch hơn sử dụng href = "#" và sau đó ngăn sự kiện mặc định chạy.

Tôi có lý do chính đáng cho câu trả lời đầu tiên cho câu hỏi này , như return false;sẽ không thực thi nếu hàm được gọi gây ra lỗi hoặc bạn có thể thêm hàm return false;vào một doSomething()hàm và sau đó quên sử dụngreturn doSomething();


7

Thử cái này:

<a href="#" onclick="return false;">My Link</a>

4

Nếu bạn chỉ có thể thay đổi hrefgiá trị, bạn nên sử dụng:

<a href="javascript:void(0);">Link Title</a>

Một giải pháp gọn gàng khác mà tôi vừa nghĩ ra là sử dụng jQuery để ngăn chặn hành động nhấp chuột xảy ra và khiến trang cuộn, nhưng chỉ cho href="#"các liên kết.

<script type="text/javascript">
    /* Stop page jumping when links are pressed */
    $('a[href="#"]').live("click", function(e) {
         return false; // prevent default click action from happening!
         e.preventDefault(); // same thing as above
    });
</script>

Chắc chắn là return falsephải sau preventDefault()dòng, nếu không bạn sẽ không bao giờ đến dòng thứ hai này?
hobailey 23/2/2016


2

Ngoài ra, bạn có thể sử dụng event.preventDefault bên trong thuộc tính onclick .

<a href="#" onclick="event.preventDefault(); doSmth();">doSmth</a>

Không cần phải viết exstra click sự kiện.



0

Khi gọi hàm, hãy làm theo nó bằng return false ví dụ:

<input  type="submit" value="Add" onclick="addNewPayment();return false;">

0

Tạo một trang chứa hai liên kết - một ở phía trên và một ở phía dưới. Khi nhấp vào liên kết trên cùng, trang phải cuộn xuống cuối trang có liên kết dưới cùng. Khi nhấp vào liên kết dưới cùng, trang phải cuộn lên trên cùng của trang.


0
<a onclick="yourfunction()">

điều này sẽ làm việc tốt không cần thêm href = "#"


0

Bạn có thể muốn kiểm tra CSS của bạn. Trong ví dụ ở đây: https://css-tricks.com/the-checkbox-hack/ there position: absolute; top: -9999px;. Điều này đặc biệt ngớ ngẩn trên Chrome, khi onclick="whatever"vẫn nhảy đến vị trí tuyệt đối của yếu tố được nhấp.

Loại bỏ position: absolute; top: -9999px;, display: none;có thể giúp đỡ.


0

Đối với Bootstrap 3 để thu gọn, nếu bạn không chỉ định mục tiêu dữ liệu trên neo và dựa vào href để xác định mục tiêu, sự kiện sẽ bị ngăn chặn. Nếu bạn sử dụng mục tiêu dữ liệu, bạn sẽ cần phải tự ngăn chặn sự kiện.

<button type="button" class="btn btn-default" data-toggle="collapse" data-target="#demo">Collapse This</button>

<div id="demo" class="collapse"> 
<p>Lorem ipsum dolor sit amet</p>
</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.