Bagaimana cara saya memodifikasi URL tanpa memuat ulang halaman?

2378

Apakah ada cara saya dapat memodifikasi URL halaman saat ini tanpa memuat ulang halaman?

Saya ingin mengakses bagian sebelum # hash jika memungkinkan.

Saya hanya perlu mengubah bagian setelah domain, jadi saya tidak melanggar kebijakan lintas domain.

 window.location.href = "www.mysite.com/page2.php";  // Sadly this reloads
Kilat
sumber
139
Agar lebih mudah untuk memahami pertanyaan, inilah yang dilakukan Facebook ketika Anda membuka foto, misalnya. Bilah url berubah menjadi mengarahkan LANGSUNG ke foto itu, sehingga Anda dapat membagikan URL tanpa kehilangan posisi Anda di situs. Ingat situs berdasarkan framing dekade terakhir? Anda hanya bisa mendapatkan url beranda, karena hanya bingkai internal yang berubah. Dan itu mengerikan.
Spidey
Meskipun history.pushState()mungkin jawaban yang tepat di sini, dalam situasi ini (tergantung pada keadaan yang tepat ...) kemungkinan menggunakan pengalihan sisi-server (seperti melalui menggunakan direktif RewriteRule dari Apache) adalah sesuatu yang mungkin ingin Anda pertimbangkan, atau setidaknya hati-hati terhadap. Hanya berpikir itu harus disebutkan!
Doin

Jawaban:

2033

Ini sekarang dapat dilakukan di Chrome, Safari, Firefox 4+, dan Internet Explorer 10pp4 +!

Lihat jawaban pertanyaan ini untuk informasi lebih lanjut: Memperbarui bilah alamat dengan URL baru tanpa hash atau memuat ulang halaman

Contoh:

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

Anda dapat menggunakan window.onpopstateuntuk mendeteksi navigasi tombol kembali / maju:

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

Untuk melihat lebih dalam tentang memanipulasi riwayat browser, lihat artikel MDN ini .

David Murdoch
sumber
272
Bagaimana facebook melakukannya di IE7?
Dominic
57
@CHiRiLo periksa history.js yang menyediakan fallback untuk browser yang tidak mendukung API riwayat HTML5.
David Murdoch
23
@ info Jika ada tanda # di URL di suatu tempat, trik itu sudah ada selama bertahun - tahun ..
Izkata
34
Apa arti "pp4 +" dari "IE10pp4 +"?
Scott Tesler
34
Pratinjau platform 4
David Murdoch
588

HTML5 memperkenalkan history.pushState()dan history.replaceState()metode, yang memungkinkan Anda untuk menambah dan memodifikasi entri riwayat.

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

Baca lebih lanjut tentang ini dari sini

Vivart
sumber
12
Mungkin tidak bekerja pada file:///untuk alasan keamanan, misalnya Firefox 30. Uji localhostdengan python -m SimpleHTTPServer.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
6
Parameter pertama diharapkan menjadi objek, bukan hanya string.
Alexis Wilke
40
IMO ini benar-benar jawaban terbaik. Jika semua yang ingin Anda lakukan adalah memperbarui URL saat ini ({}, null, strNewPath) adalah semua yang perlu Anda lakukan. Terbaik untuk menguji dulu dengan if (history.pushState) {}
Craig Jacobs
7
Anda bisa memasukkan nol untuk 2 parameter pertama jika Anda tidak ingin mengubahnya. Anda juga dapat menggunakan url absolut untuk parameter ketiga.
Andrew
3
Akan lebih baik jika Anda memasukkan beberapa informasi DI DALAM jawabannya. Saya tidak tahu, apa yang dilakukan parameter 1.
RedClover
130

Anda juga dapat menggunakan HTML5 replaceState jika Anda ingin mengubah url tetapi tidak ingin menambahkan entri ke riwayat browser:

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

Ini akan 'merusak' fungsi tombol kembali. Ini mungkin diperlukan dalam beberapa kasus seperti galeri gambar (di mana Anda ingin tombol kembali untuk kembali ke halaman indeks galeri alih-alih bergerak kembali melalui setiap gambar yang Anda lihat) sambil memberikan masing-masing gambar url unik sendiri.

George Filippakos
sumber
110

Ini solusi saya (newUrl adalah URL baru Anda yang ingin Anda ganti dengan yang sekarang):

history.pushState({}, null, newUrl);
Haimei
sumber
1
Terbaik untuk menguji terlebih dahulu dengan if (history.pushState) {} Hanya dalam kasus browser lama.
Craig Jacobs
Ini tidak berfungsi lagi Anda akan mendapatkan di Firefox: Operasi tidak aman.
kkatusic
Dan pengguna bahkan dapat mengatur bookmark dengan pendekatan itu, cantik! Sekarang saya dapat memperbarui url pada input pengguna dan ia dapat langsung mem-bookmark apa pun pengaturannya.
codepleb
107

CATATAN: Jika Anda bekerja dengan browser HTML5 maka Anda harus mengabaikan jawaban ini. Ini sekarang mungkin seperti yang dapat dilihat pada jawaban lain.

Tidak ada cara untuk memodifikasi URL di browser tanpa memuat ulang halaman. URL tersebut mewakili apa halaman yang terakhir dimuat. Jika Anda mengubahnya ( document.location) maka itu akan memuat ulang halaman.

Salah satu alasan yang jelas adalah, Anda menulis situs www.mysite.comyang terlihat seperti halaman login bank. Kemudian Anda mengubah bilah URL browser untuk mengatakan www.mybank.com. Pengguna akan sama sekali tidak menyadari bahwa mereka benar-benar melihat www.mysite.com.

Robin Day
sumber
33
Saya tidak ingin mengubah domain, hanya path dan nama file.
TheFlash
5
Ini masih tidak menghentikan potensi risiko keamanan karena browser tidak tahu bahwa domain / mysite dan domain / othersite keduanya dianggap "aman" oleh pengguna. Mungkin pertanyaannya adalah mengapa Anda ingin mengubah URL? Jika ingin mengaburkannya dari pengguna, Anda bisa menjalankan aplikasi dalam iframe.
Robin Day
5
Anda sebenarnya dapat melakukan ini dengan Flash. Ini akan memungkinkan Anda untuk memodifikasi URL tanpa membuat permintaan. Ini dimungkinkan karena Flash beroperasi di luar browser, tetapi sangat erat dengannya.
Nick Berardi
142
Saya harus mengatakan bahwa ada alasan yang sah untuk memodifikasi URL di sisi klien. Misalnya, jika Anda memiliki tabel data dengan paging, pengurutan dan pemfilteran, dan ingin hal-hal itu diberdayakan oleh Ajax, tetapi tetap perbarui URL sehingga keadaan halaman saat ini dapat di-bookmark. Saya dapat memahami risiko keamanan dengan memodifikasi nama domain (phising dll.), Tetapi mengapa browser tidak mengizinkan hanya bagian dari URL di sebelah kanan domain tingkat atas untuk dapat dimodifikasi melalui skrip?
Sunday Ironfoot
41
jawaban ini tidak lagi 100% benar. Lihat jawaban saya untuk detailnya.
David Murdoch
83
parent.location.hash = "hello";
Martin.
sumber
15
Saya ingin mengubah URL, bukan hanya hash - #mydata
TheFlash
42
Mengubah hash dapat berguna dalam ajax karena ini semacam keadaan tanpa menggunakan cookie, dapat bookmark, dan kompatibel dengan tombol kembali browser. Gmail menggunakan ini saat ini untuk membuatnya lebih ramah browser.
Matthew Lock
@Jarvis: apa bedanya?
berisik
@noisy Pelacakan sisi server tidak dapat melihat hash kecuali dikirim ke layanan pelacakan secara eksplisit.
RedYetiCo
ini tidak berguna jika Anda menggunakan kerangka MVC yang merutekan pada hash, misalnya backbone.
catbadger
27

Di browser modern dan HTML5 , ada metode yang disebut pushStatedi jendela history. Itu akan mengubah URL dan mendorongnya ke histori tanpa memuat halaman.

Anda dapat menggunakannya seperti ini, ini akan mengambil 3 parameter, 1) menyatakan objek 2) judul dan URL):

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

Ini akan mengubah URL, tetapi tidak memuat ulang halaman. Juga, itu tidak memeriksa apakah halaman itu ada, jadi jika Anda melakukan beberapa kode JavaScript yang bereaksi terhadap URL, Anda dapat bekerja dengan mereka seperti ini.

Juga ada history.replaceState()yang melakukan hal yang persis sama, kecuali itu akan mengubah sejarah saat ini daripada membuat yang baru!

Anda juga dapat membuat fungsi untuk memeriksa apakah history.pushStateada, kemudian melanjutkan dengan yang lain seperti ini:

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

Anda juga dapat mengubah #untuk <HTML5 browsers, yang tidak akan memuat ulang halaman. Itulah cara Angular menggunakan untuk melakukan SPA sesuai dengan ...

Mengubahnya #cukup mudah, lakukan seperti:

window.location.hash = "example";

Dan Anda dapat mendeteksinya seperti ini:

window.onhashchange = function () {
  console.log("#changed", window.location.hash);
}
Alireza
sumber
Akan window.onhashchangedan window.onpopstatemelakukan hal yang sama dalam hal ini?
J0ANMM
Bagaimana cara memuat konten halaman juga? Itu hanya menggantikan URL
MD. Atiqur Rahman
Muat konten seperti biasa dengan ajax.
AndroidDev
26

HTML5 replaceState adalah jawabannya, seperti yang telah disebutkan oleh Vivart dan geo1701. Namun itu tidak didukung di semua browser / versi. History.js membungkus fitur status HTML5 dan menyediakan dukungan tambahan untuk browser HTML4.

Thomas Stjernegaard Jeppesen
sumber
24

Sebelum HTML5 kita dapat menggunakan:

parent.location.hash = "hello";

dan:

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

Metode ini akan memuat ulang halaman Anda, tetapi HTML5 memperkenalkan history.pushState(page, caption, replace_url)yang seharusnya tidak memuat ulang halaman Anda.

Bersinar
sumber
2
Masalahnya history.pushState(..)adalah, bahwa jika Anda ingin mengarahkan ulang ke domain lain, kebijakan lintas domain berlaku. Sementara dengan window.location.replace(..)redirect ke domain lain dimungkinkan.
OSWorX
23

Jika yang Anda coba lakukan adalah memungkinkan pengguna untuk menandai / berbagi halaman, dan Anda tidak perlu URL yang tepat, dan Anda tidak menggunakan jangkar hash untuk hal lain, maka Anda dapat melakukannya dalam dua bagian; Anda menggunakan location.hash yang dibahas di atas, dan kemudian menerapkan pemeriksaan pada halaman beranda, untuk mencari URL dengan jangkar hash di dalamnya, dan mengarahkan Anda ke hasil selanjutnya.

Contohnya:

1) Pengguna aktif www.site.com/section/page/4

2) Pengguna melakukan beberapa tindakan yang mengubah URL menjadi www.site.com/#/section/page/6(dengan hash). Katakanlah Anda telah memuat konten yang benar untuk halaman 6 ke dalam halaman, jadi selain dari hash pengguna tidak terlalu terganggu.

3) Pengguna meneruskan URL ini ke orang lain, atau menandainya

4) Orang lain, atau pengguna yang sama di kemudian hari, pergi ke www.site.com/#/section/page/6

5) Kode pada www.site.com/pengalihan pengguna ke www.site.com/section/page/6, menggunakan sesuatu seperti ini:

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

Harapan itu masuk akal! Ini pendekatan yang berguna untuk beberapa situasi.

Jeremy Warne
sumber
17

Di bawah ini adalah fungsi untuk mengubah URL tanpa memuat ulang halaman. Ini hanya didukung untuk 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');
Suraj
sumber
2
@Green, halaman adalah judul singkat untuk status tujuan Anda. Firefox saat ini mengabaikan parameter ini, meskipun mungkin menggunakannya di masa depan. Melewati string kosong di sini harus aman terhadap perubahan metode di masa mendatang. Dari: developer.mozilla.org/en-US/docs/Web/API/…
Snook
13

Setiap perubahan lokasi (baik window.locationatau document.location) akan menyebabkan permintaan pada URL baru itu, jika Anda tidak hanya mengubah fragmen URL. Jika Anda mengubah URL, Anda mengubah URL.

Gunakan teknik penulisan ulang URL sisi-server seperti mod_rewrite Apache jika Anda tidak menyukai URL yang sedang Anda gunakan.

Gumbo
sumber
Bisakah saya menggunakan "location.pathname" ??
TheFlash
3
Tidak, mengubah atribut itu akan menyebabkan permintaan juga.
Gumbo
11

Anda dapat menambahkan tag jangkar. Saya menggunakan ini di situs saya sehingga saya dapat melacak dengan Google Analytics apa yang orang kunjungi di halaman.

Saya hanya menambahkan tag anchor dan kemudian bagian dari halaman yang ingin saya lacak:

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

Seperti yang ditunjukkan oleh Thomas Stjernegaard Jeppesen, Anda dapat menggunakan History.js untuk mengubah parameter URL sementara pengguna menavigasi melalui tautan dan aplikasi Ajax Anda.

Hampir satu tahun telah berlalu sejak jawaban itu, dan History.js tumbuh dan menjadi lebih stabil dan lintas-browser. Sekarang ini dapat digunakan untuk mengelola status riwayat di HTML5-compliant serta di banyak browser HTML4-only. Dalam demo ini, Anda dapat melihat contoh cara kerjanya (serta dapat mencoba fungsi dan batasannya.

Jika Anda memerlukan bantuan dalam cara menggunakan dan mengimplementasikan pustaka ini, saya sarankan Anda untuk melihat kode sumber dari halaman demo: Anda akan melihatnya sangat mudah dilakukan.

Akhirnya, untuk penjelasan komprehensif tentang apa yang bisa menjadi masalah tentang penggunaan hash (dan hashbangs), lihat tautan ini oleh Benjamin Lupton.

Erenor Paz
sumber
8

Gunakan history.pushState()dari API Sejarah HTML 5.

Rujuk ke API Sejarah HTML5 untuk detail lebih lanjut.

Prathamesh Rasam
sumber
7

Anda dapat menggunakan fungsi yang indah dan sederhana ini di mana saja di aplikasi Anda.

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

Anda tidak hanya dapat mengedit URL tetapi Anda dapat memperbarui judul bersamaan dengan itu.

Semua orang cukup membantu.

Dheeraj Thedijje
sumber
1
Bekerja seperti pesona bahkan untuk jangkarwindow.history.pushState('data', 'Title', '#new_location');
BIOHAZARD