หลังจากย้อนกลับไปในประวัติ Firefox JavaScript จะไม่ทำงาน


84

เมื่อฉันใช้ปุ่มย้อนกลับบน Firefox เพื่อไปยังหน้าที่เยี่ยมชมก่อนหน้านี้สคริปต์ในหน้านั้นจะไม่ทำงานอีกสคริปต์บนหน้าเว็บที่จะไม่ทำงานอีกครั้ง

มีวิธีแก้ไข / วิธีแก้ปัญหาใด ๆเพื่อให้สคริปต์ทำงานอีกครั้งเมื่อดูหน้านี้เป็นครั้งที่สองหรือไม่?

โปรดทราบว่าฉันได้ทดสอบหน้าเดียวกันบน Google Chrome และ Internet Explorer และทำงานได้ตามที่ตั้งใจไว้


นี่คือไฟล์และขั้นตอนที่ฉันใช้ในการทดสอบปัญหา:

(ไปที่ 0.html คลิกเพื่อไปที่ 1.html ปุ่มย้อนกลับ)

0.html

<html><body>
<script>
  window.onload = function() { alert('window.onload alert'); };
  alert('inline alert');
</script>
<a href="1.html">Click Me!</a>
</body></html>

1.html

<html><body>
<p>Go BACK!</p>
</body></html>

คำตอบ:


93

ตั้งค่าฟังก์ชันว่างที่จะเรียกใช้บน window.onunload:

window.onunload = function(){}; 

เช่น

<html><body>
<script type="text/javascript">
  window.onload = function() { alert('window.onload alert'); };
  window.onunload = function(){};
  alert('inline alert');
</script>
<a href="1.html">Click Me!</a>
</body></html>

ที่มา: http://www.firefoxanswer.com/firefox/672-firefoxanswer.html (เวอร์ชันที่เก็บถาวร)


2
ขอบคุณมันได้ผล คำแนะนำใด ๆ เกี่ยวกับตัวจัดการการโหลดเริ่มต้นทำอะไร (เช่นฉันกำลังลบล้างพฤติกรรมเริ่มต้นของบางประเภทที่นี่หรือไม่)
Patonza

โอเคขอบคุณฉันจะตรวจสอบ ขอบคุณอีกครั้งปัญหานี้ตามหลอกหลอนฉันมาระยะหนึ่งแล้ว :)
Patonza

มีใครรู้บ้างว่าทำไม FireFox ถึงต้องการสิ่งนี้ในขณะที่เบราว์เซอร์อื่น ๆ ไม่ทำ?
Pim Jager

7
คุณไม่ได้ลบล้างสิ่งใดเพียงแค่ป้องกันไม่ให้ Firefox แคชหน้าใน Back-Forward Cache (bfcache) developer.mozilla.org/en/DOM/window.onunload developer.mozilla.org/En/Using_Firefox_1.5_caching
Chris Haas

1
ในขณะที่มัน ควรจะทำลาย bfcache แต่น่าเสียดายที่ดูเหมือนว่ามันยังคงจำหน้าก่อนหน้านี้ได้โดยเฉพาะ URL iframe ที่โหลดจะถูกโหลดอีกครั้งเมื่อคุณย้อนกลับและหากเนื้อหาที่สร้างขึ้นจำเป็นต้องวางไว้ในเฟรมดูเหมือนจะไม่มี crossbrowser วิธีการรีเฟรชใหม่นั้น
NoBugs

76

เมื่อฉันใช้ปุ่มย้อนกลับบน Firefox เพื่อไปยังหน้าที่เยี่ยมชมก่อนหน้านี้สคริปต์ในหน้านั้นจะไม่ทำงานอีก

ถูกต้องและนั่นเป็นสิ่งที่ดี

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

คุณลักษณะนี้เรียกว่าbfcache bfcache

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

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

ดังนั้นหากคุณตั้งค่า window.onunload= function() {};สิ่งที่คุณกำลังทำคือจงใจทำลาย bfcache ซึ่งจะส่งผลให้หน้าเว็บของคุณใช้งานได้ช้าและไม่ควรใช้ยกเว้นเป็นทางเลือกสุดท้าย

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

window.onload=window.onpageshow= function() {
    alert('Hello!');
};

4
ปัญหาของฉันคือ bfcache ไม่ได้แคชทุกเพจดังนั้นฉันจึงต้องรัน js ใหม่เพื่อสร้างเนื้อหาที่หายไปใหม่ ดังนั้นการฟาดทั้งหน้าก็โอเค อย่างไรก็ตามฉันไม่ได้ใช้เหตุการณ์ window.onload ฉันใช้เหตุการณ์ jQuery document.ready คุณรู้วิธีที่จะยังคงสามารถใช้ document. พร้อมและหลีกเลี่ยงปัญหานี้ได้หรือไม่?
Patonza

โดยทั่วไปแล้ว bfcache ควรส่งคืนทั้งหน้าเหมือนตอนที่เหลืออยู่ เนื้อหาที่หายไปหลังจากกลับมาจากหน้าที่แล้วคืออะไร? (กรณีทดสอบ?) document.readyจะทำงานในลักษณะเดียวกับwindow.onload(สำหรับบางเบราว์เซอร์พวกเขาเป็นเหตุการณ์เดียวกันอยู่ดี)
Bobince

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

1
@ Jimbo: กรณีทดสอบกรุณา bfcache มีไว้เพื่อ (และในทุกกรณีที่ฉันเคยเห็นมา) รักษาสถานะที่แน่นอนของ DOM เหนือการซ่อน / แสดง องค์ประกอบที่จางหายไปจะยังคงทึบเมื่อหน้าถูกส่งกลับไปเว้นแต่สคริปต์อื่น ๆ จะเรียกใช้เพื่อซ่อนอีกครั้ง
Bobince

1
@bobince - สร้างองค์ประกอบด้วยไฟล์ CSS ที่ตั้งค่าความทึบเป็นศูนย์จากนั้นใช้ jQuery เพื่อทำให้มันจางลงในเอกสารพร้อม เมื่อย้อนกลับไปในประวัติศาสตร์จะนำ CSS สไตล์ชีทไปใช้อีกครั้ง (ศูนย์) โดยไม่คงความทึบ: 1 ที่ JS เพิ่มลงในแอตทริบิวต์ style เมื่อจางลงในครั้งแรกที่คุณเข้าชมหน้าองค์ประกอบจะจางลงจากศูนย์ถึง 1 ไปที่หน้าอื่นแล้วกดกลับและมันก็จะโปร่งใสเต็มที่
Jimbo Jonny

24

คุณสามารถตรวจสอบpersistedทรัพย์สินของpageshowงาน ตั้งค่าเป็นเท็จในการโหลดหน้าเริ่มต้น เมื่อเพจถูกโหลดจากแคชมันถูกตั้งค่าเป็นจริง

window.onpageshow = function(event) {
    if (event.persisted) {
        alert("From bfcache");
    }
};

ด้วยเหตุผลบางประการ jQuery ไม่มีคุณสมบัตินี้ในเหตุการณ์ คุณสามารถหาได้จากเหตุการณ์ดั้งเดิม

$(window).bind("pageshow", function(event) {
    if (event.originalEvent.persisted) {
        alert("From bfcache");
    }
});

ขอขอบคุณที่ให้บริการทั้งเวอร์ชันจาวาสคริปต์และ jquery! คุณพลาดวงเล็บปิดในตอนท้าย (นี่ไม่ใช่เสียงคราง!) ฉันจะทราบด้วยว่า IE และ Chrome รายงานว่าเป็นเท็จเสมอโดยไม่คำนึงถึงเพื่อประโยชน์ของผู้อื่น
Magnus Smith

ตามที่ระบุไว้โดย Magnus สิ่งนี้ใช้ไม่ได้กับฉันใน Chrome จนกว่าฉันจะลบคำสั่ง if
Justin

สิ่งนี้ใช้ได้กับฉันใน Chrome 58.0.3029.110 (64 บิต) และ FF 53.0.2 (64 บิต) โดยไม่มีการเปลี่ยนแปลงใด ๆ
kmoser

1

ต่อสายในเหตุการณ์ "onunload" ที่ไม่ทำอะไรเลย:

<html><body>
<script type="text/javascript">
  window.onload = function() { alert('window.onload alert'); };
  window.onunload = function(){}; 
  alert('inline alert');
</script>
<a href="1.html">Click Me!</a>
</body></html>

ไม่แน่ใจฉันให้คะแนนดูเหมือนจะมีคนโหวตทุกคำตอบสำหรับคำถามนี้ ...
Patonza

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

@dreagan สิ่งนี้ปิดใช้งาน bfcache แต่ไม่จำเป็นต้องเป็นแคช HTTP แคช HTTP มีชุดกฎอื่น ๆ ทั้งหมด หากคุณใช้โหมดสลีปฝั่งเซิร์ฟเวอร์คุณควรสังเกตเห็นระหว่างการคลิกย้อนกลับ Mozilla พูดเกี่ยวกับเรื่องนี้ในคำถามที่สามของพวกเขาในคำถามที่พบบ่อย BFCache
Chris Haas

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

ฉันยังไม่รู้ว่าฉันเข้าใจ เหตุใด "การโหลดเซิร์ฟเวอร์จึงเพิ่มขึ้น" หาก bfcache ในเครื่องของไคลเอ็นต์ถูกข้าม ใช่ DOM จะต้องสร้างขึ้นใหม่ แต่ HTML ควรเป็นส่วนหนึ่งของแคช HTTP ของไคลเอ็นต์ ใช่ทรัพยากรเพิ่มเติมจะต้องโหลดซ้ำ แต่สิ่งเหล่านั้นควรเป็นส่วนหนึ่งของแคช HTTP ของไคลเอ็นต์ด้วย สำหรับonpopstateคำถามนี้เมื่อเกือบห้าปีที่แล้วเหตุการณ์นั้นยังค่อนข้างใหม่และการสนับสนุนเบราว์เซอร์ไม่สอดคล้องกันมาก
Chris Haas

1

เท่าที่ฉันรู้ว่า Firefox ไม่ทำงาน onLoadเหตุการณ์ที่ด้านหลัง

มันควรจะเรียกตาม onfocus แทนจากลิงค์นี้ที่นี่


ทดสอบแล้วและ windows.onfocus เรียกใช้ได้จริงแม้ไม่ได้ตั้งค่าหน้าต่างว่างตัวจัดการการโหลด การตั้งค่า onunload เป็นวิธีแก้ปัญหาที่ดีกว่าเล็กน้อย แต่ .onfocus ก็ควรจะใช้ได้เช่นกัน ขอบคุณ :)
Patonza

1

วิธีง่ายๆในการทำให้เพจเรียกใช้ JavaScript เมื่อผู้ใช้กลับไปที่หน้านั้นโดยใช้ประวัติเบราว์เซอร์คือเหตุการณ์ OnPopState เราใช้สิ่งนี้เพื่อหยุดชั่วคราวและเล่นวิดีโอซ้ำในโฮมเพจของเรา ( https://fynydd.com )

window.onpopstate = function() {

    // Do stuff here...
};

0

สำหรับบางกรณีเช่นสามารถใช้ ajax operation url change listener ได้

$(window).on('hashchange', function() {
        ....
});
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.