ฉันจะแก้ไข URL โดยไม่ต้องโหลดหน้าซ้ำได้อย่างไร


2377

มีวิธีที่ฉันสามารถแก้ไข URL ของหน้าปัจจุบันโดยไม่ต้องโหลดหน้าใหม่หรือไม่?

ฉันต้องการเข้าถึงส่วนก่อนแฮช # ถ้าเป็นไปได้

ฉันต้องการเปลี่ยนส่วนหลังโดเมนเท่านั้นจึงไม่ใช่ว่าฉันละเมิดนโยบายข้ามโดเมน

 window.location.href = "www.mysite.com/page2.php";  // Sadly this reloads

139
เพื่อให้ง่ายต่อการเข้าใจคำถามนี่คือสิ่งที่ Facebook ทำเมื่อคุณเปิดรูปภาพ แถบ URL จะเปลี่ยนไปชี้ไปที่ภาพถ่ายโดยตรงดังนั้นคุณสามารถแชร์ URL โดยไม่สูญเสียตำแหน่งที่คุณอยู่ในไซต์ จำเว็บไซต์ตามกรอบทศวรรษที่ผ่านมา? คุณสามารถรับ URL ของหน้าแรกได้เท่านั้นเนื่องจากมีการเปลี่ยนแปลงเฟรมภายในเท่านั้น และนั่นก็แย่มาก
Spidey

ในขณะที่history.pushState()อาจเป็นคำตอบที่ถูกต้องที่นี่ในสถานการณ์นี้ (ขึ้นอยู่กับสถานการณ์ที่แน่นอน ... ) ความเป็นไปได้ของการใช้การเปลี่ยนเส้นทางฝั่งเซิร์ฟเวอร์ (เช่นผ่านการใช้คำสั่ง RewriteRule ของ Apache) เป็นสิ่งที่คุณอาจต้องการพิจารณาหรืออย่างน้อย ระวัง แค่คิดว่าควรพูดถึง!
Doin

คำตอบ:


2033

สิ่งนี้สามารถทำได้ใน Chrome, Safari, Firefox 4+ และ Internet Explorer 10pp4 +!

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

ตัวอย่าง:

 function processAjaxData(response, urlPath){
     document.getElementById("content").innerHTML = response.html;
     document.title = response.pageTitle;
     window.history.pushState({"html":response.html,"pageTitle":response.pageTitle},"", urlPath);
 }

จากนั้นคุณสามารถใช้window.onpopstateเพื่อตรวจจับการนำทางปุ่มย้อนกลับ / ไปข้างหน้า:

window.onpopstate = function(e){
    if(e.state){
        document.getElementById("content").innerHTML = e.state.html;
        document.title = e.state.pageTitle;
    }
};

สำหรับการมองในเชิงลึกมากกว่าที่ประวัติเบราเซอร์จัดการดูบทความ MDN นี้


272
Facebook ทำเช่นนั้นใน IE7 ได้อย่างไร?
Dominic

57
@CHiRiLo ดูที่history.jsซึ่งเป็นทางเลือกสำหรับเบราว์เซอร์ที่ไม่รองรับ API ประวัติ HTML5
David Murdoch

23
@infensus หากมีเครื่องหมาย # ในที่ใดที่หนึ่งของ URL, เคล็ดลับที่มีอยู่สำหรับปี ..
Izkata

34
ส่วน "pp4 +" ของ "IE10pp4 +" หมายถึงอะไร
Scott Tesler

34
ตัวอย่างแพลตฟอร์ม 4
David Murdoch

587

HTML5 แนะนำhistory.pushState()และhistory.replaceState()วิธีการที่ช่วยให้คุณสามารถเพิ่มและแก้ไขรายการประวัติตามลำดับ

window.history.pushState('page2', 'Title', '/page2.php');

อ่านเพิ่มเติมเกี่ยวกับเรื่องนี้ได้จากที่นี่


12
อาจไม่ทำงานบนfile:///เหตุผลด้านความปลอดภัยเช่น Firefox 30 การทดสอบบนด้วยlocalhost python -m SimpleHTTPServer
Ciro Santilli 冠状病毒审查六四事件法轮功

6
คาดว่าพารามิเตอร์แรกจะเป็นวัตถุไม่ใช่เพียงแค่สตริง
Alexis Wilke

40
IMO นี่เป็นคำตอบที่ดีที่สุดจริงๆ หากสิ่งที่คุณต้องการทำคืออัปเดต URL ปัจจุบัน ({}, null, strNewPath) คือสิ่งที่คุณต้องทำ ที่ดีที่สุดในการทดสอบครั้งแรกกับถ้า (history.pushState) {}
Craig Jacobs

7
คุณสามารถป้อนค่าว่างสำหรับพารามิเตอร์ 2 ตัวแรกหากคุณไม่ต้องการเปลี่ยนพารามิเตอร์ คุณยังสามารถใช้ URL แบบสัมบูรณ์สำหรับพารามิเตอร์ที่สาม
Andrew

3
มันจะดีถ้าคุณใส่ข้อมูลเพิ่มเติมในคำตอบ ฉันไม่ทราบว่าพารามิเตอร์ 1 ทำอะไร
RedClover

130

คุณยังสามารถใช้ HTML5 replaceStateหากคุณต้องการเปลี่ยน URL แต่ไม่ต้องการเพิ่มรายการในประวัติเบราว์เซอร์:

if (window.history.replaceState) {
   //prevents browser from storing history with each change:
   window.history.replaceState(statedata, title, url);
}

สิ่งนี้จะ 'ทำลาย' ฟังก์ชั่นปุ่มย้อนกลับ อาจจำเป็นต้องใช้ในบางกรณีเช่นแกลเลอรี่ภาพ (ที่คุณต้องการให้ปุ่มย้อนกลับกลับไปที่หน้าดัชนีแกลเลอรี่แทนที่จะย้ายกลับไปที่ภาพที่คุณดูทุกภาพ) ในขณะที่ให้ URL แต่ละภาพเป็นเอกลักษณ์


110

นี่คือโซลูชันของฉัน (newUrl เป็น URL ใหม่ของคุณซึ่งคุณต้องการแทนที่ด้วย URL ปัจจุบัน):

history.pushState({}, null, newUrl);

1
ดีที่สุดที่จะทดสอบก่อนด้วยถ้า (history.pushState) {} ในกรณีที่เบราว์เซอร์เก่า
Craig Jacobs

สิ่งนี้ไม่ทำงานอีกต่อไปที่คุณจะได้รับใน Firefox: การดำเนินการไม่ปลอดภัย
kkatusic

และผู้ใช้ยังสามารถตั้งค่าบุ๊คมาร์คด้วยวิธีการที่สวยงาม! ตอนนี้ฉันสามารถอัปเดต URL ในการป้อนข้อมูลของผู้ใช้และเขาสามารถคั่นหน้าการตั้งค่าของเขาได้โดยตรง
codepleb

107

หมายเหตุ: หากคุณทำงานกับเบราว์เซอร์ HTML5 คุณควรละเว้นคำตอบนี้ ตอนนี้เป็นไปได้ที่สามารถเห็นได้ในคำตอบอื่น ๆ

ไม่มีวิธีแก้ไขURLในเบราว์เซอร์โดยไม่ต้องโหลดหน้าซ้ำ URL แสดงถึงหน้าที่โหลดครั้งสุดท้าย ถ้าคุณเปลี่ยนมัน (document.location ) จากนั้นมันจะโหลดหน้าเว็บอีกครั้ง

เหตุผลหนึ่งที่ชัดเจนคือคุณเขียนเว็บไซต์www.mysite.comที่ดูเหมือนหน้าเข้าสู่ระบบของธนาคาร จากนั้นคุณเปลี่ยนแถบ URL www.mybank.comเบราว์เซอร์ที่จะพูด www.mysite.comผู้ใช้จะไม่ทราบทั้งหมดที่พวกเขากำลังมองหาจริงๆที่


33
ฉันไม่ต้องการเปลี่ยนโดเมนเพียงเส้นทางและชื่อไฟล์
TheFlash

5
สิ่งนี้ยังคงไม่หยุดความเสี่ยงด้านความปลอดภัยที่อาจเกิดขึ้นเนื่องจากเบราว์เซอร์ไม่ทราบว่าทั้งโดเมน / mysite และโดเมน / อื่น ๆ นั้นถือว่า "ปลอดภัย" โดยผู้ใช้ บางทีคำถามควรเป็นสาเหตุที่คุณต้องการเปลี่ยน URL หรือไม่ หากเป็นการปิดบังผู้ใช้คุณสามารถเรียกใช้แอปพลิเคชันของคุณภายใน iframe
วัน Robin วันที่

5
คุณสามารถทำได้ด้วย Flash มันจะช่วยให้คุณสามารถแก้ไข URL โดยไม่ต้องทำการร้องขอ สิ่งนี้เป็นไปได้เพราะ Flash ทำงานนอกเบราว์เซอร์ แต่แน่นมาก
Nick Berardi

142
ฉันต้องบอกว่ามีเหตุผลที่ถูกต้องสมบูรณ์ในการต้องการแก้ไข URL ในแถบที่อยู่ฝั่งไคลเอ็นต์ ตัวอย่างเช่นหากคุณมีสารบัญที่มีเพจจิ้งการเรียงลำดับและการกรองและต้องการให้สิ่งเหล่านั้นขับเคลื่อน Ajax แต่ยังคงอัปเดต URL เพื่อให้สถานะปัจจุบันของหน้านั้นเป็นบุ๊กมาร์ก ฉันเข้าใจความเสี่ยงด้านความปลอดภัยด้วยการแก้ไขชื่อโดเมน (ฟิชชิ่ง ฯลฯ ) แต่ทำไมเบราว์เซอร์ไม่อนุญาตให้เพียงบางส่วนของ URL ทางด้านขวาของโดเมนระดับบนสุดที่สามารถแก้ไขได้ผ่านสคริปต์
Sunday Ironfoot

41
คำตอบนี้ไม่เป็นความจริงอีกต่อไป 100% ดูคำตอบของฉันสำหรับรายละเอียด
David Murdoch

83
parent.location.hash = "hello";

15
ฉันต้องการเปลี่ยน URL ไม่ใช่แค่แฮช - #mydata
TheFlash

42
การแฮชจะมีประโยชน์ใน ajax เนื่องจากเป็นสถานะที่ไม่ต้องใช้คุกกี้สามารถคั่นหน้าและเข้ากันได้กับปุ่มย้อนกลับของเบราว์เซอร์ Gmail ใช้สิ่งนี้ทุกวันนี้เพื่อทำให้เบราว์เซอร์เป็นมิตรมากขึ้น
Matthew Lock

@ จาร์วิส: ความแตกต่างคืออะไร?
มีเสียงดัง

การติดตาม @noisy Server ไม่สามารถเห็นแฮชได้เว้นแต่จะส่งไปยังบริการติดตามอย่างชัดเจน
RedYetiCo

สิ่งนี้ไม่มีประโยชน์หากคุณใช้กรอบงาน mvc ที่กำหนดเส้นทางการแฮชตัวอย่างเช่นกระดูกสันหลัง
catbadger

27

ในปัจจุบันเบราว์เซอร์และ HTML5มีวิธีการที่เรียกว่าบนหน้าต่างpushState historyสิ่งนี้จะเปลี่ยน URL และผลักดันไปที่ประวัติโดยไม่ต้องโหลดหน้าเว็บ

คุณสามารถใช้มันเช่นนี้มันจะใช้เวลา 3 พารามิเตอร์ 1) สถานะวัตถุ 2) ชื่อและ URL):

window.history.pushState({page: "another"}, "another page", "example.html");

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

นอกจากนี้ยังมีสิ่งhistory.replaceState()ที่ทำสิ่งเดียวกันยกเว้นว่าจะแก้ไขประวัติปัจจุบันแทนที่จะสร้างใหม่!

นอกจากนี้คุณสามารถสร้างฟังก์ชั่นเพื่อตรวจสอบว่าhistory.pushStateมีอยู่หรือไม่แล้วดำเนินการกับส่วนที่เหลือดังนี้:

function goTo(page, title, url) {
  if ("undefined" !== typeof history.pushState) {
    history.pushState({page: page}, title, url);
  } else {
    window.location.assign(url);
  }
}

goTo("another page", "example", 'example.html');

นอกจากนี้คุณสามารถเปลี่ยน#สำหรับ<HTML5 browsersซึ่งจะไม่โหลดหน้าเว็บอีกครั้ง นั่นคือวิธีที่แองกูลาร์ใช้ทำสปาตามแฮชแท็ก ...

การเปลี่ยน#เป็นเรื่องง่ายทำเช่น:

window.location.hash = "example";

และคุณสามารถตรวจจับได้ดังนี้:

window.onhashchange = function () {
  console.log("#changed", window.location.hash);
}

จะwindow.onhashchangeและwindow.onpopstateทำเช่นเดียวกันในกรณีนี้หรือไม่?
J0ANMM

จะโหลดเนื้อหาของหน้าได้อย่างไร มันเพิ่งแทนที่ URL
MD Atiqur Rahman

โหลดเนื้อหาตามปกติโดยใช้ ajax
AndroidDev

26

HTML5 replaceState เป็นคำตอบดังที่ Vivart และ geo1701 พูดถึงแล้ว อย่างไรก็ตามเบราว์เซอร์ / รุ่นทั้งหมดไม่รองรับ History.jsล้อมรอบคุณสมบัติรัฐ HTML5 และให้การสนับสนุนเพิ่มเติมสำหรับเบราว์เซอร์ HTML4


24

ก่อน HTML5 เราสามารถใช้:

parent.location.hash = "hello";

และ:

window.location.replace("http:www.example.com");

วิธีนี้จะโหลดหน้าของคุณใหม่ แต่ HTML5 แนะนำสิ่งhistory.pushState(page, caption, replace_url)ที่ไม่ควรโหลดหน้าเว็บของคุณ


2
ปัญหาhistory.pushState(..)คือถ้าคุณต้องการเปลี่ยนเส้นทางไปยังโดเมนอื่นนโยบายข้ามโดเมนจะมีผล ในขณะที่มีการwindow.location.replace(..)เปลี่ยนเส้นทางไปยังโดเมนอื่นเป็นไปได้
OSWorX

23

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

ตัวอย่างเช่น

1) ผู้ใช้เปิดอยู่ www.site.com/section/page/4

2) ผู้ใช้ดำเนินการบางอย่างซึ่งเปลี่ยน URL เป็นwww.site.com/#/section/page/6(พร้อมแฮช) สมมติว่าคุณโหลดเนื้อหาที่ถูกต้องสำหรับหน้า 6 ลงในหน้านอกเหนือจากการแฮชผู้ใช้จะไม่ถูกรบกวนมากเกินไป

3) ผู้ใช้ส่ง URL นี้ไปให้คนอื่นหรือคั่นหน้าไว้

4) บุคคลอื่นหรือผู้ใช้คนเดียวกันในภายหลังจะไปที่ www.site.com/#/section/page/6

5) โค้ดในการwww.site.com/เปลี่ยนเส้นทางผู้ใช้ไปยังwww.site.com/section/page/6โดยใช้สิ่งนี้:

if (window.location.hash.length > 0){ 
   window.location = window.location.hash.substring(1);
}

หวังว่ามันสมเหตุสมผล! มันเป็นแนวทางที่มีประโยชน์สำหรับบางสถานการณ์


17

ด้านล่างเป็นฟังก์ชันในการเปลี่ยน URL โดยไม่ต้องโหลดหน้าซ้ำ รองรับ HTML5 เท่านั้น

  function ChangeUrl(page, url) {
        if (typeof (history.pushState) != "undefined") {
            var obj = {Page: page, Url: url};
            history.pushState(obj, obj.Page, obj.Url);
        } else {
            window.location.href = "homePage";
            // alert("Browser does not support HTML5.");
        }
    }

  ChangeUrl('Page1', 'homePage');

2
@Green หน้าเป็นชื่อสั้น ๆ สำหรับรัฐที่คุณกำลังย้าย Firefox ในขณะนี้จะไม่สนใจพารามิเตอร์นี้แม้ว่ามันอาจจะใช้มันในอนาคต การส่งสตริงว่างที่นี่ควรปลอดภัยต่อการเปลี่ยนแปลงในอนาคตของวิธีการ จาก: developer.mozilla.org/en-US/docs/Web/API/…
Snook

13

การเปลี่ยนแปลงใด ๆ ของ loction (อย่างใดอย่างหนึ่งwindow.locationหรือdocument.location ) จะทำให้เกิดการร้องขอใน URL ใหม่นั้นหากคุณไม่ได้เพียงแค่เปลี่ยนส่วนย่อยของ URL หากคุณเปลี่ยน URL คุณจะเปลี่ยน URL

ใช้เทคนิคการเขียน URL ฝั่งเซิร์ฟเวอร์เช่นmod_rewrite ของ Apacheหากคุณไม่ชอบ URL ที่คุณใช้อยู่ในปัจจุบัน


ฉันสามารถใช้ "location.pathname" ได้หรือไม่
TheFlash

3
ไม่การเปลี่ยนแอตทริบิวต์นั้นจะทำให้เกิดคำขอด้วย
Gumbo

11

คุณสามารถเพิ่มสมอแท็ก ฉันใช้สิ่งนี้บนเว็บไซต์ของฉันเพื่อให้สามารถติดตามด้วย Google Analytics สิ่งที่ผู้คนกำลังเยี่ยมชมบนหน้า

ฉันเพิ่งเพิ่มสมอแท็กแล้วส่วนของหน้าฉันต้องการติดตาม:

var trackCode = "/#" + urlencode($("myDiv").text());
window.location.href = "http://www.piano-chords.net" + trackCode;
pageTracker._trackPageview(trackCode);

9

ตามที่ Thomas Stjernegaard Jeppesen ชี้ให้เห็นคุณสามารถใช้History.jsเพื่อแก้ไขพารามิเตอร์ URL ในขณะที่ผู้ใช้นำทางผ่านลิงก์ Ajax และแอพของคุณ

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

หากคุณต้องการความช่วยเหลือในการใช้และนำไลบรารี่นี้มาใช้ฉันขอแนะนำให้คุณดูซอร์สโค้ดของหน้าตัวอย่าง: คุณจะเห็นว่ามันง่ายมากที่จะทำ

ในที่สุดสำหรับคำอธิบายที่ครอบคลุมเกี่ยวกับสิ่งที่อาจเป็นปัญหาเกี่ยวกับการใช้แฮช (และ hashbangs) ตรวจสอบลิงค์นี้โดย Benjamin Lupton



7

คุณสามารถใช้ฟังก์ชั่นที่สวยงามและเรียบง่ายนี้ได้ทุกที่ในแอปพลิเคชันของคุณ

function changeurl(url, title) {
    var new_url = '/' + url;
    window.history.pushState('data', 'Title', new_url);
    document.title = title;
}

คุณไม่สามารถแก้ไข URL เท่านั้น แต่คุณสามารถอัปเดตชื่อพร้อมกับได้

ค่อนข้างเป็นประโยชน์ทุกคน


1
ใช้งานได้อย่างมีเสน่ห์แม้กับสมอเรือwindow.history.pushState('data', 'Title', '#new_location');
BIOHAZARD
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.