Ajax ปุ่มย้อนกลับและการอัปเดต DOM


113

หาก javascript แก้ไข DOM ในหน้า A ผู้ใช้จะไปที่หน้า B จากนั้นกดปุ่มย้อนกลับเพื่อกลับไปที่หน้า A การแก้ไข DOM ทั้งหมดของเพจ A จะหายไปและผู้ใช้จะแสดงเวอร์ชันที่ดึงมาจากเซิร์ฟเวอร์

มันใช้งานได้ใน stackoverflow, reddit และเว็บไซต์ยอดนิยมอื่น ๆ (ลองเพิ่มความคิดเห็นทดสอบในคำถามนี้จากนั้นไปที่หน้าอื่นและกดปุ่มย้อนกลับเพื่อกลับมาความคิดเห็นของคุณจะ "หายไป")

สิ่งนี้สมเหตุสมผล แต่บางเว็บไซต์ (apple.com, basecamphq.com ฯลฯ ) กำลังบังคับให้เบราว์เซอร์ให้บริการผู้ใช้ในสถานะล่าสุดของหน้า (ไปที่http://www.apple.com/ca/search/?q=ipodคลิกที่ลิงก์ดาวน์โหลดที่ด้านบนจากนั้นคลิกปุ่มย้อนกลับ - การอัปเดต DOM ทั้งหมดจะถูกเก็บรักษาไว้)

ความไม่ลงรอยกันมาจากไหน?


ที่น่าสนใจคือ Apple จำสถานะได้โดยไม่ต้องแก้ไขแฮช .. อืม
เจมส์

ดูเหมือนว่า Apple กำลังจัดการแคชการตอบสนองเท่านั้น
BigBlondeViking

ตามที่คนอื่นแนะนำไปแล้วสิ่งนี้ไม่เกี่ยวข้องกับจาวาสคริปต์หรือ ajax คุณควรลบแท็กเหล่านั้นออกเพื่อรับคำตอบที่ถูกต้อง
BYK

ตัวอย่างของ Apple นั้นไม่ดี หากคุณทำสัญญาพื้นที่ค้นหา [เช่นผลิตภัณฑ์] ให้คลิกลิงก์ของคุณจากนั้นกดย้อนกลับ DOM จะไม่ถูกเก็บรักษาไว้ คุณกำลังมองหา Hash Solution ที่หลายคนแนะนำ
BigBlondeViking

เมื่อฉันกดปุ่มย้อนกลับ Apple จะจำหน้าผลการค้นหาที่ฉันอยู่ไม่ได้เลย ใช้ IE7 คุณต้องการวิธีแก้แฮช ดู: Facebook
Josh Stodola

คำตอบ:


106

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

เบราว์เซอร์บางตัวจะจัดเก็บสถานะปัจจุบันของหน้าเว็บทั้งหมดในที่เรียกว่า "bfcache" หรือ "page cache" สิ่งนี้ทำให้พวกเขาสามารถแสดงผลเพจซ้ำได้อย่างรวดเร็วเมื่อนำทางผ่านปุ่มย้อนกลับและไปข้างหน้าและรักษาสถานะของ DOM และตัวแปร JavaScript ทั้งหมด อย่างไรก็ตามเมื่อเพจมีเหตุการณ์ onunload เหตุการณ์เหล่านั้นอาจทำให้เพจอยู่ในสถานะไม่ทำงานดังนั้นเพจจึงไม่ถูกเก็บไว้ใน bfcache และต้องโหลดซ้ำ (แต่อาจโหลดจากแคชมาตรฐาน) และโหลดซ้ำ แสดงผลตั้งแต่เริ่มต้นรวมถึงเรียกใช้ตัวจัดการออนโหลดทั้งหมด เมื่อกลับไปที่เพจผ่าน bfcache DOM จะถูกเก็บไว้ในสถานะก่อนหน้าโดยไม่จำเป็นต้องเริ่มการทำงานของตัวจัดการ onload (เนื่องจากเพจโหลดแล้ว)

โปรดทราบว่าลักษณะการทำงานของ bfcache นั้นแตกต่างจากแคชของเบราว์เซอร์มาตรฐานที่เกี่ยวกับ Cache-Control และส่วนหัว HTTP อื่น ๆ ในหลาย ๆ กรณีเบราว์เซอร์จะแคชหน้าใน bfcache แม้ว่าจะไม่ได้เก็บไว้ในแคชมาตรฐานก็ตาม

jQuery จะแนบเหตุการณ์ยกเลิกการโหลดเข้ากับหน้าต่างโดยอัตโนมัติดังนั้นน่าเสียดายที่การใช้ jQuery จะตัดสิทธิ์ไม่ให้เพจของคุณถูกเก็บไว้ใน bfcache สำหรับการเก็บรักษา DOM และย้อนกลับ / ไปข้างหน้าอย่างรวดเร็ว. [อัปเดต: สิ่งนี้ได้รับการแก้ไขแล้วใน jQuery 1.4 เพื่อให้ใช้ได้กับ IE เท่านั้น]


3
คุณตอกมันทั้งหมด ทั้ง reddit และ stackoverflow ใช้ jquery ในขณะที่ basecamp และ apple กำลังใช้ prototypejs สิ่งนี้อธิบายทุกอย่างได้ดีทีเดียว
lubos hasko

+1 ที่น่าสนใจ (ไม่ใช่ข้ามเบราว์เซอร์) คำถามแตกต่างจากตอนที่เริ่มมาก ...
BigBlondeViking

1
มันอาจจะเป็นข้ามเบราว์เซอร์เพราะฉันสามารถทำซ้ำบน Internet Explorer ของฉันได้เช่นกัน ฉันแน่ใจว่าทุกเว็บเบราว์เซอร์ที่เปิดใช้งานจาวาสคริปต์ต้องจัดการกับปัญหานี้อยู่ดี แต่นี่เป็นเรื่องยุ่งจริงๆเมื่อคุณคิดถึงเรื่องนั้นปุ่มย้อนกลับควรพาผู้คนไปที่หน้าที่พวกเขาเห็นล่าสุดด้วยการอัปเดต DOM ทั้งหมดสถานะจาวาสคริปต์ ฯลฯ นักพัฒนาไม่ควรทำลายสิ่งนี้โดยการทำบางอย่างในเหตุการณ์ยกเลิกการโหลดและ หากเป็นเช่นนั้นเว็บเบราว์เซอร์ไม่ควรพยายามแก้ไขปัญหาโดยไม่ใช้ bfcache เลย เหตุการณ์การขนถ่ายทั้งหมดเป็นเรื่องตลกที่ยิ่งใหญ่ ฉันแน่ใจว่า 99% ของเวลาที่ใช้ในการแก้ไขการรั่วไหลของหน่วยความจำ
lubos hasko

1
โดยเฉพาะอย่างยิ่งหน่วยความจำ IE รั่วไหล :) เหตุการณ์ยกเลิกการโหลด jQuery ยังเกิดขึ้นเพื่อแก้ไขข้อบกพร่อง (ไม่เกี่ยวข้องโดยสิ้นเชิง) ใน Firefox 2 แต่ไม่จำเป็นสำหรับเบราว์เซอร์อื่น dev.jquery.com/ticket/3015 ฉันคิดว่าฉันเคยได้ยินการใช้งานอื่น ๆ สำหรับ onunload เช่นการติดตามการคลิกขาออกหรือการบันทึกสถานะเว็บแอป แต่ฉันไม่เคยมีเหตุผลที่จะใช้มันด้วยตัวเองและหากนักพัฒนาต้องการ ไซต์ช้าลงและเจ็บปวดมากขึ้นสำหรับผู้ใช้ (ฉันเกลียดการกลับไปที่หน้าความคิดเห็น reddit จะรีเซ็ตสถานะการยุบความคิดเห็น) นั่นเป็นสิทธิพิเศษของพวกเขา
ไมล์

1
เหตุการณ์การยกเลิกการโหลดจะแนบมาสำหรับ IE เท่านั้นไม่ใช่สำหรับ firefox และ chrome เวอร์ชันล่าสุดของซาฟารีรักษาสถานะ dom โดยที่ dev ไม่ต้องทำอะไรเลย
เดวิด

15

ฉันพยายามทำให้ Chrome ทำงานเหมือน Safari และวิธีเดียวที่ฉันพบว่าได้ผลคือการตั้งค่าCache-control: no-storeในส่วนหัว การดำเนินการนี้บังคับให้เบราว์เซอร์ดึงข้อมูลเพจจากเซิร์ฟเวอร์อีกครั้งเมื่อผู้ใช้กดปุ่มย้อนกลับ ไม่เหมาะ แต่ดีกว่าการแสดงหน้าเว็บที่ล้าสมัย


5
นี่คือคำตอบที่ถูกต้องสำหรับคำถามเดิม หากคุณต้องการบังคับให้เซิร์ฟเวอร์โหลดซ้ำที่ปุ่มย้อนกลับให้ใช้ 'no-store, no-cache, must-revalidate' Chrome ไม่ต้องการร้านค้าและ IE ต้องการให้ตรวจสอบความถูกต้องอีกครั้ง สำหรับเบราว์เซอร์อื่น ๆ (และ w3c) ไม่มีแคชก็เพียงพอแล้ว
woens

3

Facebook จดจำสถานะของเพจโดยการแก้ไขตัวระบุแฮชใน URL สำหรับคำขอ ajax การเปลี่ยนแปลงเหล่านี้จะถูกบันทึกไว้ในประวัติของเบราว์เซอร์ดังนั้นเมื่อผู้ใช้คลิกปุ่มย้อนกลับแฮชจะเปลี่ยนไปตามเดิม ดังนั้นจึงเป็นนัยว่าคุณจะต้องมี Javascript เพื่อตรวจสอบ has identifier และตอบสนองเมื่อเบราว์เซอร์เปลี่ยน Andreas Blixt มีกัญชาตรวจสอบสคริปต์ใช้ได้


ณ วันนี้มันไม่สามารถบอกได้ว่า facebook ทำอะไรตอนนี้
Ravinder Payal

3

สิ่งนี้ไม่เกี่ยวข้องกับสัญลักษณ์แฮช (#)

หากคุณจะตรวจสอบส่วนหัว HTTP ของ apple ก็เพียงแค่แคชหน้านั้น


ตัวอย่างของ Apple ไม่ดีพวกเขาไม่ได้ "บันทึก" สถานะของหน้าข้อสันนิษฐานของเขาว่า DOM ถูกเก็บรักษาไว้ไม่ถูกต้อง
BigBlondeViking

2

การใช้ตัวระบุแฮช / แฟรกเมนต์ URL เป็นวิธีที่ใช้กันทั่วไปในการเชื่อมโยง / จดจำสถานะในเว็บแอปพลิเคชันที่อาศัยการอัปเดต Ajax และ DOM

ตรวจสอบโครงการประวัติศาสตร์ที่เรียบง่ายสำหรับแนวคิดบางอย่าง เป็นไปได้ที่จะตรวจสอบ URL สำหรับการเปลี่ยนแปลงแฮชและ rsh ทำสิ่งนี้โดยคำนึงถึงความแตกต่างของเบราว์เซอร์


1

สำหรับใครก็ตามที่ประสบปัญหาRailsและสิ่งนี้ - ปัญหาของคุณไม่ใช่ bfcache (ฉันคิดว่ามันเป็น) - เป็นturbolinksอัญมณี นี่คือวิธีลบ

หวังว่าจะช่วยประหยัดเวลาได้บ้างและเอาหัวโขกกำแพง


0

สิ่งที่คุณกำลังมองหาคือการจัดการแฮช URL บางประเภท # ใน url มีไว้สำหรับฝั่งไคลเอ็นต์เท่านั้น

เมื่อคุณเปลี่ยนสถานะด้านหลังด้วย JS คุณจะอัปเดตข้อมูลใน # ของ url

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

ดูที่นี้:

http://ajaxpatterns.org/Unique_URLs


3
สิ่งนี้ไม่เกี่ยวข้องกับสัญลักษณ์แฮช
Luca Matteis

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