Ngăn trình duyệt tự động cuộn khi làm mới


95

Nếu bạn đi đến một trang a và cuộn xung quanh thì làm mới trang sẽ làm mới tại vị trí bạn đã rời khỏi trang đó. Điều này thật tuyệt, tuy nhiên điều này cũng xảy ra trên các trang có vị trí neo trong url. Một ví dụ là nếu bạn nhấp vào một liên kết http://example.com/post/244#comment5và làm mới trang sau khi nhìn xung quanh, bạn sẽ không ở vị trí neo và trang nhảy xung quanh. Có cách nào để ngăn chặn điều này với javascript không? Vì vậy, bất kể điều gì bạn sẽ luôn điều hướng đến mỏ neo.


Giải pháp jQuery có ổn không hay bạn muốn js đơn giản?
mrtsherman

Câu trả lời:


16

Giải pháp này không còn được khuyến nghị do những thay đổi trong hành vi của trình duyệt. Xem các câu trả lời khác.

Về cơ bản, nếu một neo được sử dụng, chúng tôi liên kết với sự kiện cuộn cửa sổ. Ý tưởng là sự kiện cuộn đầu tiên phải thuộc về việc định vị lại tự động được thực hiện bởi trình duyệt. Khi điều này xảy ra, chúng tôi tự định vị lại và sau đó loại bỏ sự kiện ràng buộc. Điều này ngăn các cuộn trang tiếp theo làm hỏng hệ thống.

$(document).ready(function() {
    if (window.location.hash) { 
        //bind to scroll function
        $(document).scroll( function() {
            var hash = window.location.hash
            var hashName = hash.substring(1, hash.length);
            var element;

            //if element has this id then scroll to it
            if ($(hash).length != 0) {
                element = $(hash);
            }
            //catch cases of links that use anchor name
            else if ($('a[name="' + hashName + '"]').length != 0)
            {
                //just use the first one in case there are multiples
                element = $('a[name="' + hashName + '"]:first');
            }

            //if we have a target then go to it
            if (element != undefined) {
                window.scrollTo(0, element.position().top);
            }
            //unbind the scroll event
            $(document).unbind("scroll");
        });
    }

});

Một trường hợp sử dụng mà tôi đang nghĩ đến cần được tính đến là nếu người dùng cuộn trang trước khi tự động cuộn xảy ra. Như tôi nhớ lại, việc cuộn tự động chỉ xảy ra sau khi trang đã tải xong. Nếu người dùng cuộn trước đó thì tự động cuộn sẽ bị hủy. Vì vậy, bạn sẽ cần một số cách để phân biệt giữa cuộn do người dùng khởi tạo và trình duyệt khởi tạo. Tôi không biết làm thế nào để làm điều này, nhưng khi tôi nhớ lại là có thể.
mrtsherman

1
Booyah! Đây là một vấn đề đêm khuya thú vị. Tôi đang nói với sếp rằng đó là lỗi của bạn khi tôi ngủ gật trên bàn làm việc. Tôi vừa thực hiện một thay đổi nhanh chóng để xóa câu lệnh trả lại. Điều này đã can thiệp vào việc bỏ liên kết mà tôi đã thêm cho sự kiện cuộn.
mrtsherman

Ban đầu, tôi nhận được điều này hoạt động trong một tệp ví dụ cơ bản nhỏ để kiểm tra nó. Khi tôi xác nhận rằng nó hoạt động, tôi cảm thấy bối rối về việc nó không hoạt động như thế nào trong dự án của tôi. Thông qua quá trình loại bỏ, tôi đã cố gắng tìm thấy một khai báo kiểu duy nhất trong tệp css của mình khiến nó bị lỗi. Đó là ứng dụng của một phông chữ bên ngoài. Tôi đã gói mã của bạn trong một hàm và hiện đang chuyển nó vào trình xử lý $ (window) .load () trong trình xử lý doc.ready. Nó hoạt động ngay bây giờ (với một chút nhấp nháy trang đầu tiên). Cảm ơn vì mã! Hãy cho tôi biết nếu đây là một bản sửa lỗi vững chắc hay không.
ThomasReggi

1
Nó sẽ không hoạt động nếu bạn có nội dung tải sau khi tải trang; Ví dụ: có 2 div sẽ được điền từ ajax với các biểu ngữ.
Decebal

@FlashThunder - bạn có thể định nghĩa "không hoạt động" không? Đăng tin nhắn trên bảng điều khiển?
mrtsherman

151

Trên Chrome, ngay cả khi bạn buộc scrollTop về 0, nó sẽ nhảy sau đó sau sự kiện cuộn đầu tiên.

Bạn nên liên kết cuộn với điều này:

$(window).on('beforeunload', function() {
    $(window).scrollTop(0);
});

Vì vậy, trình duyệt bị lừa để tin rằng nó đã ở trạng thái ban đầu trước khi làm mới.


5
Cách hữu ích hơn so với câu trả lời được chấp nhận nếu bạn không muốn lộn xộn với việc cuộn.
Dan Abramov

2
Điều này không thực hiện công việc trong Chrome 33. Ý tôi là nó sẽ cuộn lên đầu trước khi tải trang mới. Tuy nhiên, trình duyệt vẫn nhớ vị trí cuộn trước đó bằng cách nào đó và thực hiện tự động cuộn tương tự đến vị trí đó.
Haralan Dobrev

1
Đã thử nghiệm trên Chrome 36, Firefox 30 và IE 11. Hoạt động rất tốt!
Fizzix

24
Đối với triển khai không phải jQuery: window.onbeforeunload = function(){ window.scrollTo(0,0); }
ProfNandaa,

5
Tại sao bạn lại chọn sự kiện 'beforeunload' thay vì 'dỡ bỏ'. Các thử nghiệm của tôi cho thấy rằng điều cuối cùng cho phép tránh nhảy lên đầu trang trước khi trang thực sự được tải xuống bởi trình duyệt.
Aleksandr Zonov

74

Để tắt tính năng khôi phục cuộn tự động, chỉ cần thêm thẻ này vào phần đầu.

<script>history.scrollRestoration = "manual"</script>

Nó không được hỗ trợ bởi IE. Tính tương thích của trình duyệt web.


3
Đây sẽ là câu trả lời tốt nhất nếu nó có sẵn trong IE / Edge. Tuy nhiên, bạn có thể bỏ phiếu để nó được triển khai tại đây: wpdev.uservoice.com/forums/257854-microsoft-edge-developer/…
The Chewy

4
Đây thực sự phải là một câu trả lời chính xác vào năm 2019. Không có phương pháp nào khác hoạt động 100%.
Limbo

2
Có thể khẳng định đây là giải pháp tốt nhất. Các giải pháp khác ở đây không hoạt động trên Mobile Safari và có thể khá phức tạp. Điều này hoạt động hoàn hảo.
user3330820

20

Sau nhiều lần thất bại, cuối cùng tôi đã thực hiện được mẹo. Anzo đúng ở đây vì việc sử dụng beforeunloadsẽ khiến trang chuyển lên đầu khi người dùng tải lại trang hoặc nhấp vào liên kết. Vì vậy, unloadlà cách rõ ràng để làm điều này.

$(window).on('unload', function() {
   $(window).scrollTop(0);
});

Cách Javascript (Cảm ơn ProfNandaa ):

window.onunload = function(){ window.scrollTo(0,0); }

CHỈNH SỬA: 16/07/2015

Vấn đề nhảy vọt vẫn còn đó với Firefox ngay cả khi có unloadsự kiện.


3
Giải pháp này tốt hơn nhiều so với beforeunloadgiải pháp này vì nó ngăn chặn việc nhảy lên đầu trang khi tải lại và nhấp chuột neo.
BradGreens,

@BradGreens Với Chrome hiện đại, sự kiện onunload cũng được kích hoạt khi người dùng chuyển sang các tab khác, điều này không mong muốn. onbeforeunload vẫn là cách giải quyết hợp lệ.
Telvin Nguyen 11/02/19

@TelvinNguyen Bạn có thể cung cấp tài nguyên nào về cái này không? Tôi đã thử nghiệm điều này trên google chrome 72 và vẫn hoạt động tốt đối với tôi.
Janaka Dombawela

@JanakaDombawela Những gì tôi đã nêu: Chuyển tab mới sẽ gây ra sự cố là không chính xác. Tuy nhiên, bạn có thể thấy sự kiện onunload trong ví dụ này không được kích hoạt đúng cách, ngay cả với jQuery 1.9.1 so với jQuery 1.8.3. onunload là không đáng tin cậy. jsfiddle.net/6s4jhdug/3 (1.8.3) jsfiddle.net/frt45ue9 (1.9.1)
Telvin Nguyen 13/02/19

3

Đây là một cách tiếp cận tổng quát hơn. Thay vì cố gắng ngăn trình duyệt cuộn (hoặc nhảy lên đầu như mong muốn), tôi chỉ khôi phục vị trí trước đó trên trang. Tức là tôi đang ghi lại độ lệch y hiện tại của trang trong localStorage và cuộn đến vị trí này sau khi trang đã tải xong.

function storePagePosition() {
  var page_y = window.pageYOffset;
  localStorage.setItem("page_y", page_y);
}


window.addEventListener("scroll", storePagePosition);


var currentPageY;

try {
  currentPageY = localStorage.getItem("page_y");

  if (currentPageY === undefined) {
    localStorage.setItem("page_y") = 0;
  }

  window.scrollTo( 0, currentPageY );
} catch (e) {
    // no localStorage available
}

2

Bạn có thể chỉ cần đặt dấu # ở cuối để trang sẽ tải ở trên cùng.

Hoạt động trên tất cả các trình duyệt, điện thoại di động và máy tính để bàn, vì nó rất đơn giản.

$(document).ready(function() {
var url = window.location.href;
console.log(url);
if( url.indexOf('#') < 0 ) {
    window.location.replace(url + "#");
} else {
    window.location.replace(url);
}

});

// Thao tác này tải trang với dấu # ở cuối.


Nếu tôi thử điều này trực tiếp trên máy chủ của mình, nó hoạt động như một phép thuật. Nhưng, tin nhắn của tôi đang cho tôi lỗi đánh dấu. Tôi không thể hiểu đó là gì.
alice

1
nếu bạn đang sử dụng thay đổi wordpress các $ cho jQuery
Herzling

1

Điều này làm việc cho tôi.

    //Reset scroll top

    history.scrollRestoration = "manual"

    $(window).on('beforeunload', function(){
          $(window).scrollTop(0);
    });

-2

Bạn sẽ có thể.

Onload, kiểm tra xem window.location.hashcó giá trị không. Nếu có, hãy lấy phần tử có id khớp với giá trị băm. Tìm vị trí của phần tử (gọi đệ quy đến offsetTop / offsetLeft) và sau đó chuyển các giá trị đó vào window.scrollTo(x, y)phương thức.

Thao tác này sẽ cuộn trang đến phần tử mong muốn.


3
Điều này không ngăn trình duyệt thực hiện tự động cuộn. Đó là những gì câu hỏi này là về.
Haralan Dobrev
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.