ป้องกันการเลื่อนเบราว์เซอร์อัตโนมัติเมื่อรีเฟรช


99

หากคุณไปที่หน้า a แล้วเลื่อนไปรอบ ๆ จากนั้นรีเฟรชหน้านั้นจะรีเฟรชตรงจุดที่คุณทิ้งไว้ วิธีนี้ดีมาก แต่ก็เกิดขึ้นในหน้าที่มีตำแหน่งจุดยึดใน url เช่นกัน ตัวอย่างเช่นหากคุณคลิกลิงก์http://example.com/post/244#comment5และรีเฟรชหน้าหลังจากมองไปรอบ ๆ คุณจะไม่อยู่ที่จุดยึดและหน้าเว็บจะกระโดดไปมา มีวิธีใดในการป้องกันปัญหานี้ด้วยจาวาสคริปต์หรือไม่? ดังนั้นไม่ว่าคุณจะนำทางไปยังจุดยึดใดเสมอ


โซลูชัน jQuery ใช้ได้หรือคุณต้องการ js ธรรมดา?
mrtsherman

คำตอบ:


16

ไม่แนะนำวิธีแก้ปัญหานี้อีกต่อไปเนื่องจากการเปลี่ยนแปลงพฤติกรรมของเบราว์เซอร์ ดูคำตอบอื่น ๆ

โดยทั่วไปหากมีการใช้จุดยึดเราจะเชื่อมโยงกับเหตุการณ์เลื่อนของหน้าต่าง แนวคิดที่ว่าเหตุการณ์เลื่อนแรกต้องเป็นของการเปลี่ยนตำแหน่งอัตโนมัติที่ทำโดยเบราว์เซอร์ เมื่อสิ่งนี้เกิดขึ้นเราจะทำการเปลี่ยนตำแหน่งของเราเองแล้วลบเหตุการณ์ที่ถูกผูกไว้ สิ่งนี้จะป้องกันไม่ให้การเลื่อนหน้าต่อมาจากการทำงานของระบบ

$(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");
        });
    }

});

กรณีการใช้งานหนึ่งที่ฉันคิดว่าควรคำนึงถึงคือหากผู้ใช้เลื่อนหน้าก่อนที่จะเกิดการเลื่อนอัตโนมัติ ในขณะที่ฉันจำได้ว่าการเลื่อนอัตโนมัติจะเกิดขึ้นหลังจากที่โหลดหน้าเสร็จแล้วเท่านั้น หากผู้ใช้เลื่อนก่อนการเลื่อนอัตโนมัติจะถูกยกเลิก ดังนั้นคุณจะต้องมีวิธีแยกความแตกต่างระหว่างการเลื่อนโดยผู้ใช้และเบราว์เซอร์ที่เริ่มต้น ฉันไม่รู้ว่าต้องทำอย่างไร แต่อย่างที่ฉันจำได้มันเป็นไปได้
mrtsherman

1
โบย! นี่เป็นปัญหาที่สนุกสนานในตอนดึก ฉันกำลังบอกเจ้านายของฉันว่ามันเป็นความผิดของคุณตอนที่ฉันเผลอหลับไปที่โต๊ะทำงาน ฉันเพิ่งทำการเปลี่ยนแปลงอย่างรวดเร็วเพื่อลบคำสั่งส่งคืน สิ่งนี้รบกวนการคลายการผูกที่ฉันเพิ่มสำหรับเหตุการณ์เลื่อน
mrtsherman

เริ่มแรกฉันได้ทำงานนี้ภายในไฟล์ตัวอย่างพื้นฐานขนาดเล็กเพื่อตรวจสอบ เมื่อฉันยืนยันว่ามันใช้งานได้ฉันก็งงว่ามันไม่ได้ผลในโครงการของฉัน ผ่านขั้นตอนการกำจัดฉันจัดการเพื่อค้นหาการประกาศสไตล์เดียวในไฟล์ css ของฉันซึ่งทำให้เกิดข้อผิดพลาด เป็นการประยุกต์ใช้ฟอนต์ภายนอก ฉันห่อรหัสของคุณในฟังก์ชันและตอนนี้กำลังส่งไปยัง $ (window) .load () handler ภายในตัวจัดการ doc.ready ตอนนี้ตะเข็บทำงานได้แล้ว (มีการกะพริบของหน้าเริ่มต้นเล็กน้อย) ขอบคุณสำหรับรหัส! แจ้งให้เราทราบว่านี่เป็นการแก้ไขที่มั่นคงหรือไม่
ThomasReggi

1
จะไม่ทำงานหากคุณมีเนื้อหาที่โหลดหลังจากโหลดหน้า เช่นมี 2 div ที่จะเติมจาก ajax พร้อมแบนเนอร์
Decebal

@FlashThunder - คุณสามารถกำหนด "ไม่ทำงาน" ได้หรือไม่? โพสต์ข้อความคอนโซล?
mrtsherman

155

บน Chrome แม้ว่าคุณจะบังคับให้ scrollTop เป็น 0 มันจะกระโดดหลังจากเหตุการณ์เลื่อนครั้งแรก

คุณควรผูกเลื่อนกับสิ่งนี้:

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

ดังนั้นเบราว์เซอร์จึงถูกหลอกให้เชื่อว่าเป็นจุดเริ่มต้นก่อนการรีเฟรช


5
มีประโยชน์มากกว่าคำตอบที่ยอมรับหากคุณไม่ต้องการยุ่งกับการเลื่อน
Dan Abramov

2
นี่ไม่ได้ทำงานใน Chrome 33 ฉันหมายความว่ามันเลื่อนไปด้านบนก่อนที่จะโหลดหน้าใหม่ อย่างไรก็ตามเบราว์เซอร์ยังคงจำตำแหน่งการเลื่อนก่อนหน้านี้และทำการเลื่อนอัตโนมัติเดียวกันไปยังตำแหน่งนั้น
Haralan Dobrev

1
ทดสอบบน Chrome 36, Firefox 30 และ IE 11 ใช้งานได้ดีมาก!
Fizzix

26
สำหรับการใช้งานที่ไม่ใช่ jQuery: window.onbeforeunload = function(){ window.scrollTo(0,0); }
ProfNandaa

6
ทำไมคุณถึงเลือกเหตุการณ์ 'beforeunload' แทนที่จะเป็น 'unload' การทดสอบของฉันแสดงให้เห็นว่ารายการสุดท้ายอนุญาตให้หลีกเลี่ยงการข้ามไปด้านบนก่อนที่หน้าเว็บจะถูกยกเลิกการโหลดโดยเบราว์เซอร์จริงๆ
Aleksandr Zonov

79

หากต้องการปิดใช้งานการคืนค่าการเลื่อนอัตโนมัติเพียงแค่เพิ่มแท็กนี้ในส่วนหัว

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

IE ไม่รองรับ ความเข้ากันได้ของเบราว์เซอร์


3
นี่จะเป็นคำตอบที่ดีที่สุดหากมีใน IE / Edge คุณสามารถลงคะแนนเพื่อให้ใช้งานได้ที่นี่: wpdev.uservoice.com/forums/257854-microsoft-edge-developer/…
The Chewy

4
นี่น่าจะเป็นคำตอบที่ถูกต้องจริงๆในปี 2019 ไม่มีวิธีใดที่ใช้ได้ผล 100%
Limbo

2
ยืนยันได้เลยว่านี่คือทางออกที่ดีที่สุด โซลูชันอื่น ๆ ที่นี่ใช้ไม่ได้กับ Mobile Safari และอาจเป็นปัญหา นี้ทำงานได้อย่างสมบูรณ์
user3330820

22

หลังจากความล้มเหลวหลายครั้งในที่สุดฉันก็ทำเคล็ดลับได้ anzoถูกต้องที่นี่เนื่องจากการใช้beforeunloadจะทำให้หน้ากระโดดขึ้นไปด้านบนเมื่อผู้ใช้โหลดหน้าซ้ำหรือคลิกลิงก์ วิธีunloadนี้เป็นวิธีที่ชัดเจน

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

วิธี Javascript (ขอบคุณProfNandaa ):

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

แก้ไข: 16/07/2558

ปัญหาการกระโดดยังคงมีอยู่ใน Firefox แม้จะมีunloadเหตุการณ์


3
โซลูชันนี้ดีกว่าโซลูชันนี้มากbeforeunloadเนื่องจากป้องกันการกระโดดขึ้นไปที่ด้านบนของหน้าเมื่อโหลดซ้ำและคลิกที่จุดยึด
BradGreens

1
@BradGreens ด้วย Chrome สมัยใหม่เหตุการณ์ onunload จะถูกทริกเกอร์เมื่อผู้ใช้เปลี่ยนไปใช้แท็บอื่นซึ่งเป็นเรื่องที่ไม่คาดคิด onbeforeunload ยังคงเป็นวิธีแก้ปัญหาที่ถูกต้อง
Telvin Nguyen

@TelvinNguyen คุณสามารถให้ข้อมูลเกี่ยวกับเรื่องนี้ได้หรือไม่? ฉันทดสอบสิ่งนี้ใน google chrome 72 และยังใช้งานได้ดีสำหรับฉัน
Janaka Dombawela

@JanakaDombawela สิ่งที่ฉันระบุ: การเปลี่ยนแท็บใหม่ซึ่งอาจทำให้เกิดปัญหาไม่ถูกต้อง อย่างไรก็ตามคุณสามารถเห็นเหตุการณ์ onunload ในตัวอย่างนี้ทริกเกอร์ไม่ถูกต้องแม้ว่า jQuery 1.9.1 เทียบกับ jQuery 1.8.3 onunload ไม่น่าเชื่อถือ jsfiddle.net/6s4jhdug/3 (1.8.3) jsfiddle.net/frt45ue9 (1.9.1)
Telvin Nguyen

3

นี่เป็นแนวทางทั่วไปมากขึ้น แทนที่จะพยายามป้องกันไม่ให้เบราว์เซอร์เลื่อน (หรือกระโดดขึ้นไปด้านบนอย่างที่ควรจะเป็น) ฉันแค่กู้คืนตำแหน่งก่อนหน้าบนหน้า คือฉันกำลังบันทึก y-offset ปัจจุบันของเพจใน localStorage และเลื่อนไปที่ตำแหน่งนี้เมื่อโหลดเพจแล้ว

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

คุณสามารถใส่ # ต่อท้ายเพื่อโหลดหน้าเว็บที่ด้านบน

ใช้งานได้กับทุกเบราว์เซอร์มือถือและเดสก์ท็อปเพราะมันง่ายมาก

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

});

// สิ่งนี้จะโหลดหน้าโดยมี # ต่อท้าย


ถ้าฉันลองสิ่งนี้บนเซิร์ฟเวอร์ของฉันโดยตรงมันใช้งานได้เหมือนเวทมนตร์ แต่ cms ของฉันทำให้ฉันเกิดข้อผิดพลาดในการมาร์กอัป ฉันคิดไม่ออกว่ามันคืออะไร
alice

1
หากคุณใช้ wordpress เปลี่ยน $ สำหรับ jQuery
Herzlin


-2

คุณควรจะทำได้

Onload ตรวจสอบว่าwindow.location.hashมีค่าหรือไม่ ถ้าเป็นเช่นนั้นให้จับองค์ประกอบที่มีรหัสที่ตรงกับค่าแฮช ค้นหาตำแหน่งขององค์ประกอบ (เรียกซ้ำไปยัง offsetTop / offsetLeft) แล้วส่งค่าเหล่านั้นไปยังwindow.scrollTo(x, y)เมธอด

ควรเลื่อนหน้าไปยังองค์ประกอบที่ต้องการ


3
นี่ไม่ได้ป้องกันไม่ให้เบราว์เซอร์ทำการเลื่อนอัตโนมัติ นั่นคือสิ่งที่คำถามนี้เกี่ยวกับ
Haralan Dobrev
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.