แก้ไข URL ของแถบที่อยู่ในแอป AJAX เพื่อให้ตรงกับสถานะปัจจุบัน


166

ฉันกำลังเขียนแอป AJAX แต่เมื่อผู้ใช้เลื่อนผ่านแอปฉันต้องการให้ URL ในแถบที่อยู่อัปเดตแม้ว่าจะไม่มีการโหลดหน้าซ้ำ โดยทั่วไปฉันต้องการให้พวกเขาคั่นหน้าได้ทุกที่และกลับไปที่สถานะปัจจุบัน

ผู้คนจัดการกับการบำรุงรักษา RESTfulness ในแอพ AJAX อย่างไร


2
มันถูกใช้เพื่อระบุสถานะของแอพของคุณ แต่ไม่มีอะไรเกี่ยวข้องกับ "RESTfulness"
— Mohamed

29
window.history.pushState(null,'hi','page1?id=32')
— Omu

3
คำตอบที่ยอมรับถูกเขียนขึ้นเมื่อ 5 ปีก่อนและในขณะเดียวกันเราก็ได้ window.history.pushState เช่นเดียวกับ @Omu กล่าว location.hash มีปัญหามากมายและควรหลีกเลี่ยง
— pcarvalho

ฉันได้แก้ไขคำตอบเพื่อให้วิธีการ pushState โดดเด่น
— jasonjwwilliams

คำตอบ:


116

วิธีการทำเช่นนี้คือการจัดการlocation.hashเมื่อ AJAX อัปเดตส่งผลให้เกิดการเปลี่ยนแปลงสถานะที่คุณต้องการให้มี URL ที่ไม่ต่อเนื่อง ตัวอย่างเช่นหาก URL ของหน้าเว็บของคุณคือ:

http://example.com/

หากฟังก์ชันฝั่งไคลเอ็นต์เรียกใช้งานโค้ดนี้:

// AJAX code to display the "foo" state goes here.

location.hash = 'foo';

จากนั้น URL ที่แสดงในเบราว์เซอร์จะได้รับการอัปเดตเป็น:

http://example.com/#foo

วิธีนี้ช่วยให้ผู้ใช้สามารถคั่นหน้าสถานะ "foo" ของหน้าและใช้ประวัติเบราว์เซอร์เพื่อนำทางระหว่างรัฐ

ด้วยกลไกนี้คุณจะต้องแยกส่วนแฮชของ URL ในฝั่งไคลเอ็นต์โดยใช้ JavaScript เพื่อสร้างและแสดงสถานะเริ่มต้นที่เหมาะสมเนื่องจากตัวระบุส่วน (ส่วนหลัง #) จะไม่ถูกส่งไปยัง เซิร์ฟเวอร์

ปลั๊กอินแฮชเชนของ Ben Almanช่วยให้คุณใช้งาน jQuery ได้อย่างง่ายดาย


ดูเหมือนว่าคุณพูดถูก นั่นเป็นวิธีการเดียว นี่ดูเหมือนคำอธิบายรายละเอียดที่ดีสำหรับคำแนะนำของคุณ: < ajaxpatterns.org/Unique_URLs >
— jasonjwwilliams

@buymeasoda ขอบคุณสำหรับการแก้ไข; ฉันไม่แน่ใจว่าฉันคิดอะไรอยู่เมื่อฉันเขียนส่วนนั้น
— เดฟวอร์ด

1
ว้าวคำตอบนี้มีประโยชน์มาก แม้ว่าตัวอย่าง URL จะสับสนเล็กน้อยดังนั้นอาจมีการแทนที่ลิงก์ด้วยชื่อเรื่องโดยอัตโนมัติ วิธีการแทนที่สิ่งเหล่านั้นด้วย example.com และ example.com/#foo เพื่อให้เราสามารถดู URL ทั้งหมดในแบบธรรมดา
— Neil

4
@Pascal คุณสามารถทำได้ แต่เฉพาะในเบราว์เซอร์ที่รองรับ pushState ของ HTML5 ข้อมูลที่ดีเกี่ยวกับที่นี่: diveintohtml5.info/history.html
— Dave Ward

1
ฉันสิ้นสุดการเป็นแฟนตัวยงของ history.js เพื่อให้ครอบคลุมฐานสำหรับความเข้ากันได้ของเบราว์เซอร์github.com/andreasbernhard/history.js
— jocull

18

ดูเว็บไซต์เช่น book.cakephp.org เว็บไซต์นี้เปลี่ยน URL โดยไม่ต้องใช้แฮชและใช้ AJAX ฉันไม่แน่ใจว่ามันทำได้อย่างไร แต่ฉันพยายามคิดออก หากใครรู้แจ้งให้ฉันทราบ

นอกจากนี้ github.com เมื่อดูการนำทางภายในโครงการที่กำหนด


ฉันสังเกตเห็นว่าด้วย GitHub หนึ่งสัปดาห์หรือมากกว่านั้น พวกเขาทำเช่นนั้นบนโลกได้อย่างไร? ต้องย้อนกลับและตรวจสอบ
— Drew Noakes

16
ดูเหมือนว่าพวกเขากำลังใช้ฟังก์ชัน javascript pushState () สิ่งนี้จะเพิ่มประวัติของเบราว์เซอร์ของคุณ ดูมันสิ มันค่อนข้างน่าสนใจและเท่ห์
— daniel.wright

ขอบคุณสำหรับสิ่งนี้มันเป็นสิ่งที่ฉันกำลังมองหา ฉันสงสัยว่า GitHub ทำได้อย่างไร ตอนแรกฉันคิดว่ามันจะต้องโหลดซ้ำ แต่มีเพียงคำขอ AJAX ใน Opera มันโหลดหน้าเว็บซ้ำ
— kamranicus

เทคนิคที่คล้ายกันนั้นถูกใช้โดย fb ขณะที่นำทางผ่านหน้าต่างๆของกลุ่มต่างๆ คุณมีคอลัมน์การนำทางด้านซ้ายซึ่งมีการกล่าวถึงกลุ่มต่างๆ เมื่อคุณคลิกที่ชื่อกลุ่มเฉพาะการเปลี่ยนแปลง URL และเฉพาะเนื้อหาของบานหน้าต่างเนื้อหาหลักจะเปลี่ยนไปพร้อมกับ URL (ไม่มีแฮช) ดังนั้นเมื่อผู้ใช้โหลดหน้าซ้ำพวกเขาจะไม่ถูกเปลี่ยนเส้นทางไปยังหน้าแรก แต่ไปที่หน้ากลุ่ม
— Madeyedexter

17

ไม่น่าเป็นไปได้ที่ผู้เขียนต้องการโหลดซ้ำหรือเปลี่ยนเส้นทางผู้เยี่ยมชมเมื่อใช้ Ajax แต่ทำไมไม่ใช้ HTML5 ของpushState/ replaceState?

คุณจะสามารถแก้ไขแถบที่อยู่ได้มากเท่าที่คุณต้องการ รับ URL ที่ดูเป็นธรรมชาติด้วย AJAX

ลองดูรหัสในโปรเจ็กต์ล่าสุดของฉัน: http://iesus.se/


11

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

var encodedState = base64(json(state));
var newLocation = oldLocationWithoutFragment + "#" + encodedState;

document.location = newLocation; // adds new entry in browser history
document.location.replace(newLocation); // replaces current entry in browser history

วิธีแรกจะถือว่าสถานะใหม่เป็นตำแหน่งใหม่ (ดังนั้นปุ่มย้อนกลับจะนำพวกเขาไปยังตำแหน่งก่อนหน้า) หลังไม่ได้


มีวิธีเพิ่มรายการในประวัติบุ๊กมาร์กโดยไม่ต้องรีเฟรชหน้าเว็บหรือไม่ การตั้งค่าตำแหน่ง (ตามตัวอย่างแรก) จะทำให้รีเฟรชใช่มั้ย
— Drew Noakes

ทำ document.location.replace จะเปลี่ยนเส้นทางเบราว์เซอร์ไปยัง URL นั้น (ลองใช้ในคอนโซล Chrome)
— Omu

3

SWFAddress ทำงานในโครงการ Flash & Javascript และช่วยให้คุณสร้าง URL ที่คั่นหน้าได้ (ใช้วิธีแฮชที่กล่าวถึงข้างต้น) รวมถึงให้การสนับสนุนปุ่มย้อนกลับแก่คุณ

http://www.asual.com/swfaddress/


3

วิธี window.location.hash เป็นวิธีที่ต้องการในการทำสิ่งต่าง ๆ สำหรับคำอธิบายของวิธีการที่จะทำมันเป็น รูปแบบที่อาแจ็กซ์ - URL ที่ไม่ซ้ำกัน

YUI มีการนำรูปแบบนี้มาใช้เป็นโมดูลซึ่งรวมถึงการทำงานเฉพาะของ IE เพื่อให้ปุ่มย้อนกลับทำงานพร้อมกับเขียนที่อยู่ใหม่โดยใช้แฮช ผู้จัดการประวัติศาสตร์ยูอิเบราว์เซอร์

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

IE ต้องการแฮ็คที่ใช้ iframe ซึ่ง Firefox จะสร้างประวัติสองครั้งโดยใช้วิธีการเดียวกัน


3

หาก OP หรือคนอื่น ๆ ยังคงมองหาวิธีที่จะแก้ไขประวัติเบราว์เซอร์เพื่อเปิดใช้งานสถานะโดยใช้ pushState และ replaceState ตามที่ IESUS แนะนำเป็นวิธีที่ถูกต้องในการทำทันที มันเป็นข้อได้เปรียบหลักเหนือ location.hash ดูเหมือนว่ามันจะสร้าง URL จริงไม่ใช่เพียงแค่แฮช หากมีการบันทึกประวัติเบราว์เซอร์ที่ใช้แฮชจากนั้นเข้าชมอีกครั้งโดยปิดการใช้งานจาวาสคริปต์แอปจะไม่ทำงานเนื่องจากแฮชจะไม่ถูกส่งไปยังเซิร์ฟเวอร์ อย่างไรก็ตามหากมีการใช้ pushState เส้นทางทั้งหมดจะถูกส่งไปยังเซิร์ฟเวอร์ซึ่งคุณสามารถสร้างเพื่อตอบสนองเส้นทางที่เหมาะสมได้ ฉันเห็นตัวอย่างที่มีการใช้เทมเพลตหนวดแบบเดียวกันทั้งบนเซิร์ฟเวอร์และฝั่งไคลเอ็นต์ หากลูกค้าเปิดใช้งานจาวาสคริปต์เขาจะได้รับการตอบสนองที่รวดเร็วโดยหลีกเลี่ยงการไปยังเซิร์ฟเวอร์ แต่แอพพลิเคชั่นจะทำงานได้อย่างสมบูรณ์แบบหากไม่มีจาวาสคริปต์ ดังนั้นแอปสามารถลดลงอย่างงดงามได้หากไม่มีจาวาสคริปต์

นอกจากนี้ฉันเชื่อว่ามีบางกรอบออกไปด้วยชื่อเช่น history.js สำหรับเบราว์เซอร์ที่รองรับ HTML5 จะใช้ pushState แต่หากเบราว์เซอร์ไม่รองรับเบราว์เซอร์นั้นจะกลับมาใช้แฮชโดยอัตโนมัติ


2

ตรวจสอบว่าผู้ใช้ 'ใน' หน้าเมื่อคุณคลิกที่แถบ url จาวาสคริปต์บอกว่าคุณจะออกจากหน้า หากคุณเปลี่ยนแถบ URL และกด 'ENTER' พร้อมสัญลักษณ์ '#' ภายในแถบนั้นคุณจะเข้าสู่หน้านั้นอีกครั้งโดยไม่ต้องคลิกที่หน้าด้วยตนเองด้วยเคอร์เซอร์ของเมาส์จากนั้นคำสั่งเหตุการณ์ keyboad (document.onkeypress) จาก javascript จะ สามารถตรวจสอบว่ามันเข้ามาและเปิดใช้งานจาวาสคริปต์สำหรับการเปลี่ยนเส้นทางหรือไม่ คุณสามารถตรวจสอบว่าผู้ใช้อยู่ในหน้าเว็บด้วย window.onfocus หรือไม่และตรวจสอบว่าเขาออกจาก window.onblur หรือไม่

ใช่มันเป็นไปได้

;)


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