Cập nhật Ajax, nút quay lại và DOM


113

Nếu javascript sửa đổi DOM trong trang A, người dùng điều hướng đến trang B và sau đó nhấn nút quay lại để quay lại trang A. Tất cả các sửa đổi đối với DOM của trang A đều bị mất và người dùng được hiển thị với phiên bản được truy xuất ban đầu từ máy chủ.

Nó hoạt động theo cách đó trên stackoverflow, reddit và nhiều trang web phổ biến khác. (hãy thử thêm nhận xét kiểm tra vào câu hỏi này, sau đó điều hướng đến trang khác và nhấn nút quay lại để quay lại - nhận xét của bạn sẽ "biến mất")

Điều này có lý, tuy nhiên một số trang web (apple.com, basecamphq.com, v.v.) bằng cách nào đó buộc trình duyệt phải phục vụ người dùng trạng thái mới nhất của trang. (truy cập http://www.apple.com/ca/search/?q=ipod , nhấp vào nói liên kết Tải xuống ở trên cùng và sau đó nhấp vào nút quay lại - tất cả các bản cập nhật DOM sẽ được giữ nguyên)

sự không nhất quán đến từ đâu?


Điều thú vị là Apple đang ghi nhớ trạng thái mà không cần sửa đổi hàm băm .. hmmm
James

Ngoại hình của Apple như họ chỉ là thao tác bộ nhớ đệm phản ứng
BigBlondeViking

Như những người khác đã đề xuất, đây không phải là thứ liên quan đến javascript hoặc ajax. Bạn nên loại bỏ các thẻ đó để có câu trả lời chính xác.
BYK

Ví dụ về Apple là kém. Nếu bạn ký hợp đồng với một khu vực tìm kiếm [ví dụ: sản phẩm], hãy nhấp vào liên kết của bạn, sau đó nhấn trở lại, DOM sẽ không được giữ nguyên. bạn đang tìm kiếm Giải pháp băm mà nhiều người đã đề xuất.
BigBlondeViking

Khi tôi nhấn nút quay lại, Apple hoàn toàn không nhớ tôi đã truy cập trang kết quả tìm kiếm nào. Sử dụng IE7. Bạn cần một giải pháp băm. Xem: Facebook.
Josh Stodola

Câu trả lời:


106

Một câu trả lời: Trong số những thứ khác, các sự kiện dỡ hàng khiến bộ đệm lùi / chuyển tiếp bị vô hiệu .

Một số trình duyệt lưu trữ trạng thái hiện tại của toàn bộ trang web trong cái gọi là "bfcache" hoặc "page cache". Điều này cho phép họ hiển thị lại trang rất nhanh khi điều hướng qua các nút quay lại và chuyển tiếp, đồng thời duy trì trạng thái của DOM và tất cả các biến JavaScript. Tuy nhiên, khi một trang chứa các sự kiện onunload, những sự kiện đó có khả năng đưa trang vào trạng thái không hoạt động và do đó trang không được lưu trữ trong bfcache và phải được tải lại (nhưng có thể được tải từ bộ đệm chuẩn) và được hiển thị từ đầu, bao gồm chạy tất cả các trình xử lý tải lên. Khi quay lại một trang qua bfcache, DOM được giữ ở trạng thái trước đó của nó mà không cần kích hoạt các trình xử lý onload (vì trang đã được tải).

Lưu ý rằng hoạt động của bfcache khác với bộ đệm chuẩn của trình duyệt liên quan đến Cache-Control và các tiêu đề HTTP khác. Trong nhiều trường hợp, các trình duyệt sẽ lưu vào bộ nhớ đệm một trang trong bfcache ngay cả khi nó không lưu trữ trong bộ đệm chuẩn.

jQuery tự động đính kèm một sự kiện dỡ bỏ vào cửa sổ, vì vậy rất tiếc khi sử dụng jQuery sẽ khiến trang của bạn không đủ điều kiện được lưu trữ trong bfcache để bảo quản DOM và quay lại / chuyển tiếp nhanh chóng. [Cập nhật: điều này đã được sửa trong jQuery 1.4 để nó chỉ áp dụng cho IE]


3
bạn hoàn toàn đóng đinh nó. cả reddit và stackoverflow đang sử dụng jquery trong khi basecamp và apple đang sử dụng prototypejs. điều này khá nhiều giải thích mọi thứ.
Lubos hasko

1 thú vị (không qua trình duyệt mặc dù) câu hỏi là khác xa so với khi nó bắt đầu ...
BigBlondeViking

1
nó có thể sẽ là trình duyệt chéo vì tôi cũng có thể tái tạo nó trên Internet Explorer của mình. Tôi chắc chắn rằng mọi trình duyệt web có bật javascript đều phải giải quyết vấn đề này. nhưng điều này thực sự là một mớ hỗn độn, khi bạn nghĩ về điều đó, nút quay lại phải luôn đưa mọi người đến trang mà họ đã xem lần cuối cùng với tất cả các bản cập nhật DOM, trạng thái javascript, v.v. các nhà phát triển không nên phá vỡ điều này bằng cách làm gì đó trong sự kiện dỡ bỏ và nếu có, trình duyệt web không nên cố gắng khắc phục sự cố bằng cách hoàn toàn không sử dụng bfcache. toàn bộ sự kiện dỡ hàng là một trò đùa lớn. Tôi chắc chắn rằng 99% thời gian nó được sử dụng để vá lỗi rò rỉ bộ nhớ.
Lubos hasko

1
Cụ thể, bộ nhớ IE bị rò rỉ. :) Sự kiện dỡ bỏ jQuery cũng xảy ra để sửa một lỗi (hoàn toàn không liên quan) trong Firefox 2. Nhưng nó không cần thiết đối với các trình duyệt khác. dev.jquery.com/ticket/3015 Tôi cho rằng tôi đã nghe nói về các cách sử dụng khác cho onunload, như theo dõi nhấp chuột ra ngoài hoặc lưu trạng thái ứng dụng web, nhưng tôi chưa bao giờ có lý do để tự mình sử dụng nó và nếu các nhà phát triển muốn thực hiện các trang web chậm hơn và gây khó khăn hơn cho người dùng của họ (tôi ghét cách điều hướng trở lại trang nhận xét reddit đặt lại trạng thái thu gọn nhận xét), đó là đặc quyền của họ.
Miles

1
Sự kiện dỡ tải chỉ được đính kèm cho IE không dành cho firefox và chrome. Phiên bản mới nhất của safari giữ nguyên trạng thái dom mà không cần nhà phát triển phải làm bất cứ điều gì.
David

15

Tôi đã cố gắng làm cho Chrome hoạt động giống như Safari và cách duy nhất tôi thấy rằng nó hoạt động là đặt Cache-control: no-storetrong tiêu đề. Điều này buộc trình duyệt phải tìm nạp lại trang từ máy chủ khi người dùng nhấn nút quay lại. Không lý tưởng, nhưng tốt hơn là được hiển thị một trang lỗi thời.


5
Đây là câu trả lời chính xác cho câu hỏi ban đầu. Nếu bạn muốn buộc máy chủ tải lại trên nút quay lại, hãy sử dụng điều khiển bộ nhớ cache 'no-store, no-cache, must-revalidate'. Chrome muốn không có cửa hàng và IE muốn xác thực lại. Đối với các trình duyệt khác (và w3c) không có bộ nhớ cache là đủ.
woens

3

Facebook ghi nhớ trạng thái trang bằng cách sửa đổi mã định danh băm trong URL cho các yêu cầu ajax. Những thay đổi này được ghi lại trong lịch sử trình duyệt, vì vậy khi người dùng nhấp vào nút quay lại, hàm băm sẽ thay đổi thành như trước đó. Vì vậy, có nghĩa là bạn sẽ cần một số Javascript để giám sát mã nhận dạng có và phản ứng khi nó được trình duyệt thay đổi. Andreas Blixt có sẵn một tập lệnh giám sát băm .


đến ngày hôm nay nó diesn't làm như vậy có thể cho tôi biết những gì facebook làm tại
Ravinder Payal

3

Điều này không liên quan gì đến ký hiệu băm (#).

Nếu bạn kiểm tra các tiêu đề HTTP của apple, nó chỉ đơn giản là bộ nhớ đệm của trang.


Táo ví dụ là người nghèo, họ không được "tiết kiệm" nhà nước trang, giả định của ông DOM được bảo tồn nó sai
BigBlondeViking

2

Sử dụng mã định danh băm / phân đoạn URL là một cách khá phổ biến để kết nối / ghi nhớ trạng thái trong ứng dụng web dựa trên các bản cập nhật Ajax và DOM.

Kiểm tra dự án Lịch sử Thực sự Đơn giản để biết một số ý tưởng. Có thể theo dõi URL để biết các thay đổi đối với hàm băm và rsh thực hiện điều này, có tính đến sự khác biệt của trình duyệt.


1

Đối với bất kỳ ai đang gặp vấn đề với Railsvà điều này - vấn đề của bạn không phải là bfcache (tôi nghĩ là vậy) - đó là turbolinksviên ngọc quý. Đây là cách để loại bỏ nó.

Hy vọng rằng điều này sẽ giúp bạn tiết kiệm thời gian và đập đầu vào tường.


0

Những gì bạn đang tìm kiếm là một số kiểu quản lý băm URL. # Trong url chỉ dành cho phía khách hàng.

Khi bạn thay đổi trạng thái của mặt sau bằng JS, thì bạn cập nhật dữ liệu trong # của url.

Ngoài ra, bạn thêm một số kiểu thăm dò theo dõi xem băm có thay đổi hay không và tải trạng thái của trang dựa trên dữ liệu mới trong băm.

Hãy xem này:

http://ajaxpatterns.org/Unique_URLs


3
điều này không liên quan gì đến biểu tượng băm.
Luca Matteis

3
Bạn đã nhầm, anh ấy đang tìm cách phổ biến nhất để bảo toàn trạng thái trang trong một giải pháp AJAX.
BigBlondeViking
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.