Làm cách nào để sửa đổi URL mà không cần tải lại trang?


2377

Có cách nào để tôi có thể sửa đổi URL của trang hiện tại mà không cần tải lại trang không?

Tôi muốn truy cập phần trước khi băm # nếu có thể.

Tôi chỉ cần thay đổi phần sau tên miền, vì vậy nó không giống như tôi vi phạm các chính sách tên miền chéo.

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

139
Để dễ hiểu câu hỏi hơn, đây là những gì Facebook làm khi bạn mở một bức ảnh chẳng hạn. Thanh url thay đổi để trỏ TRỰC TIẾP vào ảnh đó, vì vậy bạn có thể chia sẻ URL mà không mất vị trí của bạn trong trang web. Ghi nhớ các trang web dựa trên khung vào thập kỷ trước? Bạn chỉ có thể lấy url trang chủ, vì chỉ các khung bên trong đang thay đổi. Và điều đó thật tồi tệ.
Spidey

Mặc dù history.pushState()có lẽ là câu trả lời đúng ở đây, trong tình huống này (tùy thuộc vào hoàn cảnh chính xác ...) khả năng sử dụng chuyển hướng phía máy chủ (chẳng hạn như thông qua chỉ thị RewriteRule của Apache) là điều bạn có thể muốn xem xét, hoặc ít nhất là coi chừng. Chỉ cần nghĩ rằng nó nên được đề cập!
Doin

Câu trả lời:


2033

Điều này hiện có thể được thực hiện trong Chrome, Safari, Firefox 4+ và Internet Explorer 10pp4 +!

Xem câu trả lời của câu hỏi này để biết thêm thông tin: Cập nhật thanh địa chỉ bằng URL mới mà không cần băm hoặc tải lại trang

Thí dụ:

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

Sau đó, bạn có thể sử dụng window.onpopstateđể phát hiện điều hướng nút quay lại / chuyển tiếp:

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

Để có cái nhìn sâu hơn về thao tác lịch sử trình duyệt, hãy xem bài viết MDN này .


272
Làm thế nào để facebook làm điều đó trong IE7?
Đaminh

57
@CHiRiLo kiểm tra history.js cung cấp dự phòng cho các trình duyệt không hỗ trợ API lịch sử HTML5.
David Murdoch

23
@infrade Nếu có dấu # trong URL ở đâu đó, mánh khóe đó đã tồn tại trong nhiều năm ..
Izkata

34
Phần "pp4 +" của "IE10pp4 +" nghĩa là gì?
Scott Tesler

34
xem trước nền tảng 4
David Murdoch

587

HTML5 đã giới thiệu history.pushState()history.replaceState()các phương thức, cho phép bạn thêm và sửa đổi các mục lịch sử, tương ứng.

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

Tìm hiểu thêm về điều này từ đây


12
Có thể không hoạt động file:///vì lý do an toàn, ví dụ Firefox 30. Thử nghiệm localhostvới python -m SimpleHTTPServer.
Ciro Santilli 冠状 病毒 审查 事件

6
Tham số đầu tiên dự kiến ​​là một đối tượng, không chỉ là một chuỗi.
Alexis Wilke

40
IMO đây thực sự là câu trả lời tốt nhất. Nếu tất cả những gì bạn muốn làm là cập nhật URL hiện tại ({}, null, strNewPath) là tất cả những gì bạn cần làm. Tốt nhất để kiểm tra đầu tiên với if (history.pushState) {}
Craig Jacobs

7
bạn chỉ có thể nhập null cho 2 tham số đầu tiên nếu bạn không muốn thay đổi chúng. Bạn cũng có thể sử dụng một url tuyệt đối cho tham số thứ ba.
Andrew

3
Sẽ thật tốt nếu bạn đặt thêm một số thông tin chỉ vào câu trả lời. Tôi không có ý tưởng, tham số 1 làm gì.
RedClover

130

Bạn cũng có thể sử dụng HTML5 thay thếState nếu bạn muốn thay đổi url nhưng không muốn thêm mục vào lịch sử trình duyệt:

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

Điều này sẽ 'phá vỡ' chức năng nút quay lại. Điều này có thể được yêu cầu trong một số trường hợp, chẳng hạn như thư viện hình ảnh (nơi bạn muốn nút quay lại quay lại trang chỉ mục thư viện thay vì quay lại qua từng hình ảnh bạn đã xem) trong khi cung cấp cho mỗi hình ảnh một url duy nhất của riêng mình.


110

Đây là giải pháp của tôi (newUrl là URL mới mà bạn muốn thay thế bằng URL hiện tại):

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

1
Tốt nhất để kiểm tra đầu tiên với if (history.pushState) {} Chỉ trong trường hợp trình duyệt cũ.
Craig Jacobs

Điều này không hoạt động nữa mà bạn sẽ nhận được trong Firefox: Hoạt động không an toàn.
kkatusic

Và người dùng thậm chí có thể thiết lập một bookmark với cách tiếp cận đó, thật đẹp! Bây giờ tôi có thể cập nhật url trên đầu vào của người dùng và anh ta có thể đánh dấu trực tiếp bất cứ cài đặt nào của anh ta.
codepleb

107

LƯU Ý: Nếu bạn đang làm việc với trình duyệt HTML5 thì bạn nên bỏ qua câu trả lời này. Điều này bây giờ có thể như có thể được nhìn thấy trong các câu trả lời khác.

Không có cách nào để sửa đổi URL trong trình duyệt mà không tải lại trang. URL đại diện cho những gì trang được tải cuối cùng là. Nếu bạn thay đổi nó ( document.location) thì nó sẽ tải lại trang.

Một lý do rõ ràng là, bạn viết một trang web www.mysite.comtrông giống như trang đăng nhập ngân hàng. Sau đó, bạn thay đổi thanh URL trình duyệt để nói www.mybank.com. Người dùng sẽ hoàn toàn không biết rằng họ đang thực sự nhìn vào www.mysite.com.


33
Tôi không muốn thay đổi tên miền, chỉ có đường dẫn và tên tệp.
TheFlash

5
Điều này vẫn không ngăn được các rủi ro bảo mật tiềm ẩn vì trình duyệt không biết rằng tên miền / mysite và domain / otherite đều được người dùng coi là "an toàn". Có lẽ câu hỏi nên là tại sao bạn muốn thay đổi URL? Nếu nó che khuất nó khỏi người dùng, bạn chỉ cần chạy ứng dụng của mình trong iframe.
Ngày Robin

5
Bạn thực sự có thể làm điều này với Flash. Nó sẽ cho phép bạn sửa đổi URL mà không cần yêu cầu. Điều này là có thể bởi vì Flash hoạt động bên ngoài trình duyệt, nhưng rất chặt chẽ với nó.
Nick Berardi

142
Tôi phải nói rằng có những lý do hoàn toàn hợp lệ cho việc muốn sửa đổi URL trong phía máy khách của thanh địa chỉ. Chẳng hạn, nếu bạn có một bảng dữ liệu với phân trang, sắp xếp và lọc và muốn những thứ đó được cung cấp Ajax, nhưng vẫn cập nhật URL để trạng thái hiện tại của trang có thể đánh dấu được. Tôi có thể hiểu các rủi ro bảo mật khi sửa đổi tên miền (lừa đảo, v.v.), nhưng tại sao các trình duyệt không cho phép chỉ một phần URL ở bên phải của tên miền cấp cao nhất có thể sửa đổi thông qua tập lệnh?
Chủ nhật Iron feet

41
Câu trả lời này không còn đúng 100% nữa. Xem câu trả lời của tôi để biết chi tiết.
David Murdoch

83
parent.location.hash = "hello";

15
Tôi muốn thay đổi URL, không chỉ là hàm băm - #mydata
TheFlash

42
Thay đổi hàm băm có thể hữu ích trong ajax vì đây là một loại trạng thái mà không sử dụng cookie, có thể đánh dấu và tương thích với các nút quay lại của trình duyệt. Gmail sử dụng điều này ngày nay để làm cho nó thân thiện hơn với trình duyệt.
Khóa Matthew

@Jarvis: sự khác biệt là gì?
ồn ào

@noisy Theo dõi phía máy chủ không thể thấy băm trừ khi được gửi đến dịch vụ theo dõi một cách rõ ràng.
RedYetiCo

điều này không hữu ích nếu bạn đang sử dụng khung mvc định tuyến trên hàm băm, ví dụ như đường trục.
catbadger

27

Trong các trình duyệt và HTML5 hiện đại , có một phương thức được gọi pushStatetrên cửa sổ history. Điều đó sẽ thay đổi URL và đẩy nó vào lịch sử mà không cần tải trang.

Bạn có thể sử dụng nó như thế này, nó sẽ lấy 3 tham số, 1) tiêu đề đối tượng trạng thái 2) và một URL):

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

Điều này sẽ thay đổi URL, nhưng không tải lại trang. Ngoài ra, nó không kiểm tra xem trang có tồn tại hay không, vì vậy nếu bạn thực hiện một số mã JavaScript đang phản ứng với URL, bạn có thể làm việc với chúng như thế này.

Ngoài ra, có history.replaceState()những thứ thực hiện chính xác điều tương tự, ngoại trừ nó sẽ sửa đổi lịch sử hiện tại thay vì tạo một cái mới!

Ngoài ra, bạn có thể tạo một chức năng để kiểm tra nếu history.pushStatetồn tại, sau đó tiếp tục với phần còn lại như thế này:

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

Ngoài ra bạn có thể thay đổi #cho <HTML5 browsers, mà không load lại trang. Đó là cách Angular sử dụng để làm SPA theo hashtag ...

Thay đổi #là khá dễ dàng, làm như:

window.location.hash = "example";

Và bạn có thể phát hiện ra nó như thế này:

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

Sẽ window.onhashchangewindow.onpopstatelàm tương tự trong trường hợp này?
J0ANMM

Làm thế nào để tải nội dung trang là tốt? Nó chỉ thay thế URL
MD. Atiqur Rahman

Tải nội dung như bạn thường làm với ajax.
AndroidDev

26

Thay thế HTML5 là câu trả lời, như đã được đề cập bởi Vivart và Geo1701. Tuy nhiên, nó không được hỗ trợ trong tất cả các trình duyệt / phiên bản. History.js bao bọc các tính năng trạng thái HTML5 và cung cấp hỗ trợ bổ sung cho các trình duyệt HTML4.


24

Trước HTML5 chúng ta có thể sử dụng:

parent.location.hash = "hello";

và:

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

Phương pháp này sẽ tải lại trang của bạn, nhưng HTML5 đã giới thiệu history.pushState(page, caption, replace_url)rằng không nên tải lại trang của bạn.


2
Vấn đề với history.pushState(..)là, nếu bạn muốn chuyển hướng đến một tên miền khác, chính sách tên miền chéo có hiệu lực. Trong khi với window.location.replace(..)chuyển hướng đến một tên miền khác là có thể.
OSWorX

23

Nếu những gì bạn đang cố gắng làm là cho phép người dùng đánh dấu / chia sẻ trang và bạn không cần nó phải là URL chính xác và bạn không sử dụng neo băm cho bất cứ điều gì khác, thì bạn có thể làm điều này trong hai các bộ phận; bạn sử dụng location.hash đã thảo luận ở trên và sau đó thực hiện kiểm tra trên trang chủ, để tìm URL có neo băm trong đó và chuyển hướng bạn đến kết quả tiếp theo.

Ví dụ:

1) Người dùng đang bật www.site.com/section/page/4

2) Người dùng thực hiện một số hành động thay đổi URL thành www.site.com/#/section/page/6(với hàm băm). Giả sử bạn đã tải đúng nội dung cho trang 6 vào trang, vì vậy ngoài hàm băm, người dùng không quá băn khoăn.

3) Người dùng chuyển URL này cho người khác hoặc đánh dấu nó

4) Một người nào khác, hoặc cùng một người dùng vào một ngày sau đó, đi đến www.site.com/#/section/page/6

5) Mã www.site.com/chuyển hướng người dùng đến www.site.com/section/page/6, sử dụng một cái gì đó như thế này:

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

Hy vọng rằng có ý nghĩa! Đó là một cách tiếp cận hữu ích cho một số tình huống.


17

Dưới đây là chức năng thay đổi URL mà không cần tải lại trang. Nó chỉ được hỗ trợ cho 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, trang là một tiêu đề ngắn cho trạng thái mà bạn đang di chuyển. Firefox hiện đang bỏ qua tham số này, mặc dù nó có thể sử dụng nó trong tương lai. Truyền chuỗi rỗng ở đây sẽ an toàn trước các thay đổi trong tương lai của phương thức. Từ: developer.mozilla.org/en-US/docs/Web/API/
mẹo

13

Mọi thay đổi của vị trí (hoặc window.locationhoặc document.location) sẽ gây ra yêu cầu trên URL mới đó, nếu bạn không chỉ thay đổi đoạn URL. Nếu bạn thay đổi URL, bạn thay đổi URL.

Sử dụng các kỹ thuật viết lại URL phía máy chủ như mod_rewrite của Apache nếu bạn không thích các URL bạn đang sử dụng.


Tôi có thể sử dụng "location.pathname" không ??
TheFlash

3
Không, thay đổi thuộc tính đó cũng sẽ gây ra yêu cầu.
Gumbo

11

Bạn có thể thêm các thẻ neo. Tôi sử dụng điều này trên trang web của mình để tôi có thể theo dõi với Google Analytics những gì mọi người đang truy cập trên trang.

Tôi chỉ cần thêm một thẻ neo và sau đó là một phần của trang tôi muốn theo dõi:

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

9

Như Thomas Stjernegaard Jeppesen đã chỉ ra, bạn có thể sử dụng History.js để sửa đổi các tham số URL trong khi người dùng điều hướng qua các liên kết và ứng dụng Ajax của bạn.

Gần một năm đã trôi qua kể từ câu trả lời đó và History.js đã phát triển và trở nên ổn định hơn và đa trình duyệt. Bây giờ nó có thể được sử dụng để quản lý các trạng thái lịch sử trong các trình duyệt tuân thủ HTML5 cũng như trong nhiều trình duyệt chỉ có HTML4. Trong bản demo này, bạn có thể thấy một ví dụ về cách thức hoạt động của nó (cũng như có thể thử các chức năng và giới hạn của nó.

Nếu bạn cần bất kỳ trợ giúp nào về cách sử dụng và triển khai thư viện này, tôi khuyên bạn nên xem mã nguồn của trang demo: bạn sẽ thấy nó rất dễ thực hiện.

Cuối cùng, để giải thích toàn diện về những gì có thể là vấn đề về việc sử dụng băm (và hashbang), hãy xem liên kết này của Benjamin Lupton.



7

Bạn có thể sử dụng chức năng đẹp và đơn giản này để mọi nơi trên ứng dụng của bạn.

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

Bạn không chỉ có thể chỉnh sửa URL mà còn có thể cập nhật tiêu đề cùng với nó.

Khá hữu ích cho mọi người.


1
Hoạt động như một bùa mê ngay cả đối với neowindow.history.pushState('data', 'Title', '#new_location');
BIOHAZARD
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.