กวดวิชาที่ดีสำหรับการใช้ 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.