กวดวิชาที่ดีสำหรับการใช้ API ประวัติ HTML5 (Pushstate?) [ปิด]


168

ฉันกำลังมองหาการใช้ HTML5 History API เพื่อแก้ไขปัญหาการเชื่อมโยงเชิงลึกกับเนื้อหาที่โหลด AJAX แต่ฉันพยายามดิ้นรนเพื่อหลีกเลี่ยงปัญหา มีใครรู้แหล่งข้อมูลที่ดีบ้างไหม?

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

การวิจัยเริ่มต้นของฉันดูเหมือนจะชี้ไปที่ History API ภายใน JS และวิธี pushState

http://html5demos.com/history

คำตอบ:


181

สำหรับบทช่วยสอนที่ยอดเยี่ยมหน้า Mozilla Developer Network ในฟังก์ชั่นนี้คุณจะต้อง: https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history

น่าเสียดายที่ HTML5 History API นั้นมีการใช้งานที่แตกต่างกันไปในเบราว์เซอร์ HTML5 ทั้งหมด (ทำให้ไม่สอดคล้องกันและมีความผิดพลาด) และไม่มีทางเลือกอื่นสำหรับเบราว์เซอร์ HTML4 โชคดีที่History.jsให้การทำงานร่วมกันข้ามสำหรับเบราว์เซอร์ HTML5 (ทำให้มั่นใจว่าเบราว์เซอร์ HTML5 ทั้งหมดทำงานตามที่คาดไว้) และเป็นทางเลือกที่ให้แฮชสำรองสำหรับเบราว์เซอร์ HTML4 (รวมถึงการสนับสนุนข้อมูลข้อมูลชื่อ pushState และ

คุณสามารถอ่านเพิ่มเติมเกี่ยวกับ History.js ได้ที่นี่: https://github.com/browserstate/history.js

สำหรับบทความเกี่ยวกับ Hashbangs VS Hashes VS API ประวัติ HTML5 ดูที่นี่: https://github.com/browserstate/history.js/wiki/Intelligent-State-Handling


25
เสียบตัวเองที่ไร้ยางอาย โพสต์ที่ยอดเยี่ยมและปลั๊กอินแม้ว่า :)
Purag

33

ฉันได้รับประโยชน์มากมายจาก 'Dive to HTML 5' คำอธิบายและการสาธิตนั้นง่ายขึ้นและตรงประเด็น บทที่ประวัติศาสตร์ - http://diveintohtml5.info/history.html และการสาธิตประวัติ - http://diveintohtml5.info/examples/history/fer.html


1
กวดวิชาที่ยอดเยี่ยมแน่นอน URL กลายเป็นdiveintohtml5.infoในระหว่างนี้ อาจต้องการอัปเดตคำตอบ
Dan Dascalescu

28

โปรดทราบว่าในขณะที่ใช้ HTML5 pushstate หากผู้ใช้คัดลอกหรือคั่นหน้าลิงก์ลึก ๆ และเข้าชมอีกครั้งจากนั้นจะเป็นการเข้าสู่เซิร์ฟเวอร์โดยตรงซึ่งจะเป็น 404 ดังนั้นคุณต้องพร้อมสำหรับมันและแม้แต่ห้องสมุด pushstate js ก็ไม่ได้ช่วยอะไร คุณ. ทางออกที่ง่ายที่สุดคือการเพิ่มกฎการเขียนซ้ำลงในเซิร์ฟเวอร์ Nginx หรือ Apache ของคุณดังนี้:

Apache (ใน vhost ของคุณหากคุณใช้อยู่):

<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;

นั่นคือคำตอบที่แท้จริง สิ่งนี้ไม่มีอยู่ใน wiki / tutorials ของ Balupton ในความเป็นจริง History.js ไม่ใช้แฮชดังนั้นคุณต้องใช้การเปลี่ยนเส้นทาง. htaccess!
adriendenat

13
โดยอุดมคติเซิร์ฟเวอร์ / แอปของคุณควรตอบสนองต่อเส้นทางที่เหมาะสมโดยไม่จำเป็นต้องเขียนซ้ำนี้
sholsinger

เห็นด้วยยกเว้นในกรณีของกรอบจาวาสคริปต์ที่ทันสมัยจำนวนมากเช่น Backbone.js, Spine, Ember และอื่น ๆ ทั้งหมดนี้เป็นแอปพลิเคชัน JavaScript "หน้าเดียว" เป็นหลัก เราสามารถหาทางออกของการให้บริการเทมเพลตเขียนแบ็กเอนด์สำหรับ SEO และอื่น ๆ แต่ในขณะเดียวกันก็จำเป็น
Mauvis Ledford

*ขวา. ฉันเขียนเกี่ยวกับเรื่องนี้ในรายละเอียดเพิ่มเติมได้ที่นี่: readystate4.com/2012/05/17/…
Mauvis Ledford

6

ข้อมูลจำเพาะประวัติศาสตร์ HTML5เป็นโวหาร

history.pushState()ไม่ได้ส่งpopstateเหตุการณ์หรือโหลดหน้าใหม่ด้วยตัวเอง มันหมายถึงการผลักดันสถานะในประวัติศาสตร์เท่านั้น นี่คือคุณสมบัติ "เลิกทำ" สำหรับแอปพลิเคชันหน้าเดียว คุณต้องส่งpopstateเหตุการณ์ด้วยตนเองหรือใช้history.go()เพื่อนำทางไปยังสถานะใหม่ แนวคิดคือเราเตอร์สามารถฟังpopstateเหตุการณ์และนำทางสำหรับคุณ

บางสิ่งที่ควรทราบ:

  • history.pushState()และhistory.replaceState()อย่าส่งpopstateเหตุการณ์
  • history.back(),, history.forward()และปุ่มย้อนกลับและไปข้างหน้าของเบราว์เซอร์ทำการจัดส่งpopstateกิจกรรม
  • history.go()และhistory.go(0)ทำการโหลดหน้าเต็มและไม่ส่งpopstateเหตุการณ์
  • history.go(-1)(ด้านหลัง 1 หน้า) และhistory.go(1)(ไปข้างหน้า 1 หน้า) ทำการส่งpopstateเหตุการณ์

คุณสามารถใช้ประวัติ API เช่นนี้เพื่อผลักดันสถานะใหม่และส่งเหตุการณ์ป๊อบสเตท

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

จากนั้นฟังpopstateกิจกรรมด้วยเราเตอร์


1
มันเป็นเพียงฉันหรือnew PopStateEvent(...)ดูเหมือนจะไม่ทำงานใน IE11? มีวิธีแก้ปัญหาที่ทุกคนรู้หรือไม่?
David Alan Hjelle

ดูเหมือนว่า IE 11 ต้องการบางสิ่งเช่น: var pop_state_event = document.createEvent('Event'); pop_state_event.initEvent('popstate', true, true); window.dispatchEvent(pop_state_event);
David Alan Hjelle

4

คุณสามารถลองใช้Davis.jsซึ่งจะช่วยให้คุณกำหนดเส้นทางใน JavaScript โดยใช้ pushState เมื่อมีให้บริการและหากไม่มี JavaScript จะทำให้รหัสฝั่งเซิร์ฟเวอร์ของคุณจัดการคำขอได้



2

คุณอาจต้องการดูปลั๊กอิน jQuery นี้ พวกเขามีตัวอย่างมากมายในเว็บไซต์ของพวกเขา http://www.asual.com/jquery/address/


อีกครั้งโซลูชันนี้ดูเหมือนว่าจะล้มเหลวเมื่อปิด JS ฉันคิดว่า history API มีประสิทธิภาพในการทำงานร่วมกับ modrewrite เพื่อให้ลิงก์นั้นประมวลผลในอินสแตนซ์แรกโดยเซิร์ฟเวอร์โดยไม่จำเป็นต้องเปลี่ยนเส้นทางจากเลเยอร์ JS
Mild Fuzz

คุณอยู่ในเส้นทางที่ถูกต้องกับ modrewrite ทางออกของการจัดการประวัติ API และการจัดการเมื่อผู้ใช้ไม่มี JS เป็นสองสิ่งที่แยกจากกันจริงๆ หากคุณไม่มี JS คุณต้องจัดการผู้ใช้ด้วย hrefs มาตรฐานและการตอบกลับของเซิร์ฟเวอร์ API ประวัติสามารถสร้างเป็นแบบ "ดีที่มี" ถ้าเบราว์เซอร์ของผู้ใช้รองรับ
Nathan Totten

ทั้งตัวอย่าง Express และ State ที่มาพร้อมกับ jQuery Address 1.3 ทำงานได้ค่อนข้างดีเมื่อปิดการใช้งาน JavaScript อันที่สองใช้ PHP กับ mod_rewrite
Rostislav

ชั้นเชิงของฉัน ฉันต้องการสร้างเว็บไซต์โดยไม่มี JS เพิ่มองค์ประกอบ AJAX จากนั้นใช้ประวัติเพื่อเขียน URL ใหม่โดยคงการเชื่อมโยงอย่างลึกซึ้ง ในทางทฤษฎีมันควรจะเป็นวิธีที่ดีกว่าที่ฉันเคยเห็นเพราะเว็บไซต์จะไม่ขึ้นอยู่กับ AJAX ในทุกขั้นตอน
Mild Fuzz

1
-1 เนื่องจากที่อยู่ jQuery ไม่ใช่พอร์ตโดยตรงของ API สถานะ HTML5 - ไม่สนับสนุนข้อมูลหรือชื่อและแทนที่สถานะ
balupton

2

ฉันได้เขียนนามธรรมเราเตอร์ที่ง่ายมากที่ด้านบนของ History.js เรียกStateRouter.js มันอยู่ในช่วงเริ่มต้นของการพัฒนา แต่ฉันใช้มันเป็นโซลูชันการกำหนดเส้นทางในแอปพลิเคชันหน้าเดียวที่ฉันกำลังเขียน เช่นเดียวกับคุณฉันพบว่า History.js นั้นยากที่จะเข้าใจโดยเฉพาะอย่างยิ่งเมื่อฉันค่อนข้างใหม่กับ JavaScript จนกระทั่งฉันเข้าใจว่าคุณต้องการ (หรือควรมี) การกำหนดเส้นทางที่เป็นนามธรรมอยู่ด้านบนเนื่องจากมันแก้ไขระดับต่ำ ปัญหา.

ตัวอย่างรหัสง่ายๆนี้ควรแสดงให้เห็นถึงวิธีการใช้งาน:

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();

นี่คือซอเล็ก ๆ น้อย ๆ ที่ฉันได้ปรุงเพื่อแสดงให้เห็นถึงการใช้งาน


1
ซอนี้ไม่ทำงานสำหรับฉันใน Chrome บน Mac มันพ่นข้อผิดพลาด (การอ้างอิง Uncaught ข้อผิดพลาด: ไม่ได้กำหนด
staterouter

@DrewT ขอบคุณซอเสียเพราะการเปลี่ยนแปลงที่ github.com แต่ฉันได้ทำงานกับมัน
aknuds1

ใช่ทำงานตอนนี้ขอบคุณสำหรับการตอบสนองอย่างรวดเร็ว
DrewT

1

หากมี jQuery คุณสามารถใช้jQuery BBQ ได้


ดูเหมือนว่าจะล้มเหลวเมื่อปิด JS
Mild Fuzz

อาจเป็นจริง - ยังไม่ได้ตรวจสอบ ฉันคิดว่าคุณจะมีปัญหากับวิธีการใช้ js-library ทั้งหมด มันขึ้นอยู่กับการจัดการส่วนแฮชของ URL
sprugman

1
นั่นคือจุดสำคัญของ API ประวัติ HTML5 - มันไม่ทำลายอะไรเลย
balupton

2
@MildFuzz คอมพิวเตอร์ดูเหมือนว่าจะล้มเหลวโดยไม่มีแหล่งพลังงาน! ฉันคิดว่าคุณมีข้อผิดพลาด ID-10-T ...
เอริค Hodonsky

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