Hướng dẫn tốt để sử dụng API Lịch sử HTML5 (Pushstate?) [Đã đóng]


168

Tôi đang xem xét sử dụng API Lịch sử HTML5 để giải quyết các vấn đề liên kết sâu với nội dung được tải AJAX, nhưng tôi đang cố gắng để khởi đầu. Có ai biết bất kỳ nguồn lực tốt?

Tôi muốn sử dụng điều này vì nó có vẻ là một cách tuyệt vời để cho phép khả năng những người được gửi các liên kết có thể không bật JS. Nhiều giải pháp thất bại khi ai đó có JS gửi liên kết đến ai đó mà không có.

Nghiên cứu ban đầu của tôi dường như chỉ ra API Lịch sử trong JS và phương thức PushState.

http://html5demos.com/history

Câu trả lời:


181

Để có một hướng dẫn tuyệt vời, trang Mozilla Developer Network về chức năng này là tất cả những gì bạn cần: https://developer.mozilla.org/en/DOM/Manipulation_the_browser_history

Thật không may, API Lịch sử HTML5 được triển khai khác nhau trong tất cả các trình duyệt HTML5 (khiến nó không nhất quán và có lỗi) và không có dự phòng cho các trình duyệt HTML4. May mắn thay, History.js cung cấp khả năng tương thích chéo cho các trình duyệt HTML5 (đảm bảo tất cả các trình duyệt HTML5 hoạt động như mong đợi) và tùy chọn cung cấp dự phòng băm cho các trình duyệt HTML4 (bao gồm hỗ trợ duy trì cho dữ liệu, tiêu đề, chức năng PushState và thay thếState).

Bạn có thể đọc thêm về History.js tại đây: https://github.com/browserstate/history.js

Để biết bài viết về Hashbang VS Hashing VS Lịch sử HTML5, hãy xem tại đây: https://github.com/browserstate/history.js/wiki/Intellect-State-Handling


25
Xấu hổ tự cắm. Tuyệt vời bài viết và plugin mặc dù. :)
Purag


28

Hãy ghi nhớ trong khi sử dụng HTML5 Pushstate nếu người dùng sao chép hoặc đánh dấu một liên kết sâu và truy cập lại, đó sẽ là một máy chủ trực tiếp tấn công 404, vì vậy bạn cần sẵn sàng cho nó và thậm chí thư viện js của Pushstate sẽ không giúp đỡ bạn. Giải pháp đơn giản nhất là thêm quy tắc viết lại vào máy chủ Nginx hoặc Apache của bạn như vậy:

Apache (trong vhost của bạn nếu bạn đang sử dụng một):

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    RewriteRule ^index\.html$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.html [L]
 </IfModule>

Nginx

rewrite ^(.+)$ /index.html last;

ĐÓ là câu trả lời thực sự. Đây không phải là nơi có trên wiki / hướng dẫn về Lịch sử của Balupton, v.v. Trên thực tế, History.js không sử dụng hàm băm nên bạn cần sử dụng chuyển hướng .htaccess!
adriendenat

13
Lý tưởng nhất là máy chủ / ứng dụng của bạn sẽ đáp ứng tuyến đường một cách thích hợp mà không cần phải viết lại.
sholsinger

Đồng ý, ngoại trừ trường hợp có nhiều khung JavaScript hiện đại như Backbone.js, Spine, Ember, v.v ... Đây đều là những ứng dụng JavaScript "một trang" về cơ bản. Người ta có thể tìm ra một giải pháp phục vụ mẫu viết phụ trợ cho SEO, ect, nhưng trong lúc này điều này là cần thiết.
Mauvis Ledford

*đúng. Tôi viết về điều này chi tiết hơn ở đây: readystate4.com/2012/05/17/ từ
Mauvis Ledford

6

Thông số lịch sử HTML5 là kỳ quặc.

history.pushState()không tự mình gửi một popstatesự kiện hoặc tải một trang mới. Nó chỉ có nghĩa là để đẩy nhà nước vào lịch sử. Đây là một tính năng "hoàn tác" cho các ứng dụng trang đơn. Bạn phải tự gửi một popstatesự kiện hoặc sử dụng history.go()để điều hướng đến trạng thái mới. Ý tưởng là một bộ định tuyến có thể lắng nghe popstatecác sự kiện và thực hiện điều hướng cho bạn.

Một số điều cần lưu ý:

  • history.pushState()history.replaceState()không gửi popstatecác sự kiện.
  • history.back(), history.forward()và các nút quay lại và chuyển tiếp của trình duyệt thực hiện popstatecác sự kiện.
  • history.go()history.go(0)thực hiện tải lại toàn bộ trang và không gửi popstatecác sự kiện.
  • history.go(-1)(quay lại 1 trang) và history.go(1)(chuyển tiếp 1 trang) để gửi popstatecác sự kiện.

Bạn có thể sử dụng API lịch sử như thế này để đẩy trạng thái mới VÀ gửi một sự kiện popstate.

history.pushState({message:'New State!'}, 'New Title', '/link'); window.dispatchEvent(new PopStateEvent('popstate', { bubbles: false, cancelable: false, state: history.state }));

Sau đó lắng nghe các popstatesự kiện với một bộ định tuyến.


1
Có phải chỉ có tôi, hoặc new PopStateEvent(...)dường như không hoạt động trong IE11? Có một cách giải quyết mà bất cứ ai biết?
David Alan Hjelle

Có vẻ như IE 11 cần một cái gì đó như: var pop_state_event = document.createEvent('Event'); pop_state_event.initEvent('popstate', true, true); window.dispatchEvent(pop_state_event);
David Alan Hjelle

4

Bạn có thể thử Davis.js , nó cung cấp cho bạn định tuyến trong JavaScript của bạn bằng cách sử dụng PushState khi có sẵn và không có JavaScript, nó cho phép mã phía máy chủ của bạn xử lý các yêu cầu.



2

Bạn có thể muốn xem qua plugin jQuery này. Họ có rất nhiều ví dụ trên trang web của họ. http://www.asual.com/jquery/address/


Một lần nữa, giải pháp này dường như thất bại khi tắt JS. Tôi nghĩ API lịch sử có khả năng hoạt động cùng với modrewrite để các liên kết luôn được máy chủ xử lý trong trường hợp đầu tiên, mà không cần chuyển hướng từ lớp JS.
Fuzz nhẹ

Bạn đang đi đúng hướng với modrewrite. Giải pháp quản lý API lịch sử và xử lý khi người dùng không có JS thực sự là hai điều riêng biệt. Nếu bạn không có JS, bạn phải xử lý người dùng bằng các phản hồi tiêu chuẩn và máy chủ. API lịch sử có thể được xây dựng dưới dạng "tốt để có" nếu trình duyệt của người dùng hỗ trợ.
Nathan T'd

Cả hai mẫu Express và State đi kèm với Địa chỉ jQuery 1.3 đều hoạt động khá tốt khi JavaScript bị tắt. Cái thứ hai sử dụng PHP với mod_rewrite.
Rostislav

Chính xác là chiến thuật của tôi. Tôi dự định xây dựng trang web mà không cần JS, thêm các yếu tố AJAX và sau đó sử dụng lịch sử để viết lại URL, duy trì liên kết sâu. Về mặt lý thuyết, nó phải là một phương pháp tốt hơn bất kỳ phương pháp nào tôi đã thấy vì trang web sẽ không phụ thuộc vào AJAX, ở bất kỳ giai đoạn nào
Mild Fuzz

1
-1 vì Địa chỉ jQuery không phải là cổng trực tiếp của API trạng thái HTML5 - không hỗ trợ dữ liệu hoặc tiêu đề và thay thếState.
balupton

2

Tôi đã viết một bản tóm tắt bộ định tuyến rất đơn giản trên đầu trang History.js , được gọi là StateRouter.js . Đó là trong giai đoạn đầu phát triển, nhưng tôi đang sử dụng nó làm giải pháp định tuyến trong một ứng dụng một trang mà tôi đang viết. Giống như bạn, tôi thấy History.js rất khó nắm bắt, đặc biệt là khi tôi còn khá mới với JavaScript, cho đến khi tôi hiểu rằng bạn thực sự cần (hoặc nên có) một sự trừu tượng hóa định tuyến trên nó, vì nó giải quyết được mức độ thấp vấn đề.

Mã ví dụ đơn giản này sẽ cho thấy cách nó được sử dụng:

var router = new staterouter.Router();
// Configure routes
router
  .route('/', getHome)
  .route('/persons', getPersons)
  .route('/persons/:id', getPerson);
// Perform routing of the current state
router.perform();

Đây là một mẹo nhỏ tôi đã pha chế để chứng minh việc sử dụng nó.


1
Fiddle này không hoạt động với tôi trong Chrome trên Mac. Nó ném một lỗi. (Uncaught ReferenceError: staterouter không được xác định)
DrewT

@DrewT Cảm ơn, fiddle đã bị hỏng do thay đổi tại github.com, nhưng tôi đã làm việc xung quanh nó.
aknuds1

Yup, làm việc bây giờ nhờ phản ứng nhanh chóng.
DrewT

1

nếu jQuery có sẵn, bạn có thể sử dụng jQuery BBQ


Điều này dường như thất bại với JS đã tắt.
Fuzz nhẹ

điều đó có thể đúng - chưa nhìn vào nó. Tôi nghĩ rằng bạn sẽ gặp vấn đề đó với tất cả các cách tiếp cận dựa trên thư viện js. Họ dựa trên việc thao túng phần băm của url.
spugman

1
đó là điểm của API Lịch sử HTML5 - nó không phá vỡ bất cứ điều gì
balupton

2
@MildFuzz Máy tính dường như thất bại khi không có nguồn điện! Tôi nghĩ rằng bạn có lỗi ID-10-T ...
Eric Hodonsky

1
Trớ trêu thay, đó là bạn có sự thất thường
Mild Fuzz
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.