Di - window.location.hash - Ubah?

558

Saya menggunakan Ajax dan hash untuk navigasi.

Apakah ada cara untuk memeriksa apakah window.location.hashberubah seperti ini?

http://example.com/blah # 123 hingga http://example.com/blah # 456

Ini berfungsi jika saya memeriksanya ketika dokumen dimuat.

Tetapi jika saya memiliki navigasi berbasis # hase itu tidak berfungsi ketika saya menekan tombol kembali pada browser (jadi saya melompat dari bla # 456 ke bla # 123).

Itu terlihat di dalam kotak alamat, tapi saya tidak bisa menangkapnya dengan JavaScript.

MilMike
sumber
6
Periksa plugin jquery ini: github.com/cowboy/jquery-hashchange
Xavi
9
History.js mendukung Fungsi Manajemen Status HTML5 (jadi Anda tidak perlu menggunakan hash lagi!) Dan dengan anggun menurunkannya ke browser HTML4 menggunakan hashchanges. Ini mendukung jQuery, MooTools dan Prototype di luar kotak.
balupton
@balupton, Sebenarnya kita masih perlu menggunakan hash untuk memberikan umpan balik kepada pengguna bahwa "halaman baru" telah dimasukkan ke dalam riwayatnya, kecuali jika Anda menggunakan pengubahan URL sebagai umpan balik.
Pacerier
1
[Hasher] github.com/millermedeiros/hasher
Vishnoo Rath
hmm ... Saya pikir Anda perlu moar jQuery
RaisingAgent

Jawaban:

617

Satu-satunya cara untuk benar-benar melakukan ini (dan adalah bagaimana 'reallysimplehistory' melakukan ini), adalah dengan menetapkan interval yang terus memeriksa hash saat ini, dan membandingkannya dengan apa yang sebelumnya, kami melakukan ini dan membiarkan pelanggan berlangganan untuk berubah acara yang kami jalankan jika hash berubah .. itu tidak sempurna tetapi browser benar-benar tidak mendukung acara ini secara asli.


Perbarui untuk menjaga agar jawaban ini tetap segar:

Jika Anda menggunakan jQuery (yang hari ini harus agak mendasar untuk sebagian besar) maka solusi yang bagus adalah dengan menggunakan abstraksi yang jQuery berikan kepada Anda dengan menggunakan sistem kejadiannya untuk mendengarkan acara hashchange pada objek jendela.

$(window).on('hashchange', function() {
  //.. work ..
});

Yang menyenangkan di sini adalah Anda dapat menulis kode yang tidak perlu khawatir tentang dukungan hashchange, namun Anda DO perlu melakukan beberapa keajaiban, dalam bentuk fitur jQuery yang agak kurang dikenal jQuery acara khusus .

Dengan fitur ini Anda pada dasarnya menjalankan beberapa kode pengaturan untuk acara apa pun, pertama kali seseorang mencoba menggunakan acara dengan cara apa pun (seperti mengikat ke acara).

Dalam kode pengaturan ini Anda dapat memeriksa dukungan browser asli dan jika browser tidak mengimplementasikannya secara native, Anda dapat mengatur timer tunggal untuk melakukan polling untuk perubahan, dan memicu acara jQuery.

Ini benar-benar melepaskan ikatan kode Anda dari kebutuhan untuk memahami masalah dukungan ini, pelaksanaan acara khusus semacam ini sepele (untuk mendapatkan versi kerja 98% sederhana), tetapi mengapa melakukan itu ketika orang lain sudah melakukannya .

meandmycode
sumber
7
IE8 tidak. Lebih banyak lagi
Sergey Ilinsky
28
Firefox build terbaru (3,6 alpha) juga sekarang mendukung acara hash asli yang diubah: developer.mozilla.org/en/DOM/window.onhashchange Tentu saja patut dilakukan pemeriksaan untuk acara ini, tetapi perhatikan bahwa IE8 akan memberi tahu Anda acara tersebut ada ketika sedang berjalan dalam mode compat IE7 .. sayangnya acara tidak menyala .. Anda harus memeriksa acara dan bahwa browser tampaknya tidak menjadi IE7 .. sigh (atau upaya untuk memicu acara dengan metode IEE FireEvent).
meandmycode
8
Pada saat penulisan, WebKit juga memecat hashchangeacara, sedangkan Safari (stabil) belum.
jholster
51
Hanya untuk menambah lagi pembaruan lain, hashchangeacara sekarang banyak didukung: caniuse.com/#search=hash
Paystey
19
Apakah saya satu-satunya yang menganggap jawaban jQuery yang tidak diminta itu menyebalkan?
Luc
290

HTML5 menentukan hashchangeacara . Acara ini sekarang didukung oleh semua browser modern . Dukungan telah ditambahkan di versi browser berikut:

  • Internet Explorer 8
  • Firefox 3.6
  • Chrome 5
  • Safari 5
  • Opera 10.6
Miles
sumber
20
Pembaruan: FF 5, Safari 5, dan Chrome 12 mendukung acara ini pada Juni 2011.
james.garriss
2
Ini adalah halaman CanIUse untuk hashchange . Inilah hashchange pada quirksmode . Dukungan IE bersifat buggy sehubungan dengan sensitivitas kasus.
Tobu
3
@semuanya, tidak perlu terus menambahkan jawaban di bagian komentar - itulah gunanya tombol "Edit". :)
Michael Martin-Smucker
15
penggunaan:window.onhashchange = function() { doYourStuff(); }
Chris
4
Dokumentasi MDN untuk acara hashchange .
Dabowheel
52

Perhatikan bahwa dalam kasus Internet Explorer 7 dan Internet Explorer 9 ifstatment akan memberikan true (untuk "onhashchange" di windows), tetapi window.onhashchangeitu tidak akan pernah menyala, jadi lebih baik menyimpan hash dan memeriksanya setelah setiap 100 milidetik apakah itu diubah atau tidak untuk semua versi Internet Explorer.

    if (("onhashchange" in window) && !($.browser.msie)) {
         window.onhashchange = function () {
              alert(window.location.hash);
         }
         // Or $(window).bind( 'hashchange',function(e) {
         //       alert(window.location.hash);
         //   });
    }
    else {
        var prevHash = window.location.hash;
        window.setInterval(function () {
           if (window.location.hash != prevHash) {
              prevHash = window.location.hash;
              alert(window.location.hash);
           }
        }, 100);
    }

EDIT - Sejak jQuery 1.9, $.browser.msietidak didukung. Sumber: http://api.jquery.com/jquery.browser/

Khan Salahuddin
sumber
14

Ada banyak trik untuk menangani History dan window.location.hash di browser IE:

  • Seperti yang dikatakan pertanyaan awal, jika Anda beralih dari halaman a.html # b ke a.html # c, lalu tekan tombol kembali, browser tidak tahu halaman itu telah berubah. Izinkan saya mengatakannya dengan sebuah contoh: window.location.href akan menjadi 'a.html # c', tidak masalah jika Anda berada di a.html # b atau a.html # c.

  • Sebenarnya, a.html # b dan a.html # c disimpan dalam riwayat hanya jika elemen '<a name="#b">' dan '<a name="#c">' ada sebelumnya di halaman.

  • Namun, jika Anda meletakkan iframe di dalam halaman, navigasikan dari a.html # b ke a.html # c di iframe itu lalu tekan tombol kembali, iframe.contentWindow.document.location.href berubah seperti yang diharapkan.

  • Jika Anda menggunakan 'document.domain = something ' dalam kode Anda, maka Anda tidak dapat mengakses iframe.contentWindow.document.open () '(dan banyak Manajer Sejarah melakukannya)

Saya tahu ini bukan respons nyata, tapi mungkin catatan IE-History berguna bagi seseorang.

Sergio Cinos
sumber
11

Ben Alman memiliki plugin jQuery yang bagus untuk menangani hal ini: http://benalman.com/projects/jquery-hashchange-plugin/

Jika Anda tidak menggunakan jQuery, itu mungkin referensi yang menarik untuk membedah.

CJ.
sumber
Plugin Ben Alman tampaknya tidak lagi dipertahankan. Ada beberapa garpu.
Mnebuerquo
9

Anda dapat dengan mudah menerapkan pengamat (metode "menonton") pada properti "hash" objek "window.location".

Firefox memiliki implementasi sendiri untuk menonton perubahan objek , tetapi jika Anda menggunakan beberapa implementasi lainnya (seperti Perhatikan perubahan properti objek dalam JavaScript ) - untuk browser lain, itu akan melakukan trik.

Kode akan terlihat seperti ini:

window.location.watch(
    'hash',
    function(id,oldVal,newVal){
        console.log("the window's hash value has changed from "+oldval+" to "+newVal);
    }
);

Maka Anda dapat mengujinya:

var myHashLink = "home";
window.location = window.location + "#" + myHashLink;

Dan tentu saja itu akan memicu fungsi pengamat Anda.

gion_13
sumber
Lebih baik gunakan: window.location.href daripada window.location.
Codebeat
3
Dia sedang menonton window.location.hash, bukan window.location.
tidak terdefinisi
1
@BrianMortenson: menurut dokumen ( developer.mozilla.org/en-US/docs/JavaScript/Reference/… ), Anda harus menerapkan watchobjek yang memiliki properti yang berubah dan Anda ingin mengamatinya.
gion_13
@ gion_13 Ya, itulah yang ingin saya tunjukkan. Dengan 'Dia' yang saya maksud adalah Anda, dan itu diarahkan pada komentar Erwinus. Seharusnya aku lebih jelas. Terima kasih atas komentar klarifikasi Anda.
tidak terdefinisi
7

Saya menggunakan ini dalam aplikasi reaksi untuk membuat URL menampilkan parameter yang berbeda tergantung pada tampilan pengguna yang aktif.

Saya menyaksikan menggunakan parameter hash

window.addEventListener('hashchange', doSomethingWithChangeFunction());

Kemudian

doSomethingWithChangeFunction () { 
    // Get new hash value
    let urlParam = window.location.hash;
    // Do something with new hash value
};

Bekerja dengan baik, bekerja dengan tombol browser maju dan mundur dan juga dalam riwayat browser.

Sprose
sumber
1
dalam addEventListenerpanggilan Anda, Anda harus menghapus ()daridoSomethingWithChangeFunction
Jason S
Bisakah Anda memberikan alasan untuk menghapus ()? Saya tahu ini akan bekerja dengan baik, dan sedikit kode sebagian besar merupakan pilihan yang lebih baik, tetapi ini tampaknya pilih-pilih kecuali ada alasan kuat untuk mendukungnya?
Sprose
6
? seharusnya tidak bekerja (). The addEventListenerFungsi mengharuskan Anda untuk lulus dalam suatu fungsi. doSomethingWithChangeFunctionadalah suatu fungsi. doSomethingWithChangeFunction()adalah nilai pengembalian fungsi itu, yang dalam hal ini bukan fungsi.
Jason S
6

Implementasi yang layak dapat ditemukan di http://code.google.com/p/reallysimplehistory/ . Satu-satunya (dan juga) masalah dan bug yang dimilikinya adalah: di Internet Explorer memodifikasi hash lokasi secara manual akan mengatur ulang seluruh tumpukan riwayat (ini adalah masalah browser dan tidak dapat dipecahkan).

Catatan, Internet Explorer 8 memang memiliki dukungan untuk acara "hashchange", dan karena itu menjadi bagian dari HTML5, Anda mungkin mengharapkan browser lain untuk mengejar ketinggalan.

Sergey Ilinsky
sumber
1

Implementasi hebat lainnya adalah jQuery History yang akan menggunakan acara onhashchange asli jika didukung oleh browser, jika tidak maka akan menggunakan iframe atau interval dengan tepat untuk browser untuk memastikan semua fungsi yang diharapkan berhasil ditiru. Ini juga menyediakan antarmuka yang bagus untuk mengikat ke kondisi tertentu.

Proyek lain yang juga perlu diperhatikan adalah jQuery Ajaxy yang merupakan perpanjangan dari jQuery History untuk menambahkan ajax ke dalam campuran. Seperti ketika Anda mulai menggunakan ajax dengan hash itu cukup rumit !

balupton
sumber
1
var page_url = 'http://www.yoursite.com/'; // full path leading up to hash;
var current_url_w_hash = page_url + window.location.hash; // now you might have something like: http://www.yoursite.com/#123

function TrackHash() {
    if (document.location != page_url + current_url_w_hash) {
        window.location = document.location;
    }
    return false;
}
var RunTabs = setInterval(TrackHash, 200);

Itu saja ... sekarang, kapan pun Anda menekan tombol kembali atau maju, halaman akan dimuat ulang sesuai nilai hash baru.

batman
sumber
jangan gunakan string eval
Vitim.us
1

Saya telah menggunakan path.js untuk routing sisi klien saya. Saya menemukan ini cukup ringkas dan ringan (juga telah dipublikasikan ke NPM), dan menggunakan navigasi berbasis hash.

path.js NPM

path.js GitHub

Tom
sumber
0

Saya menggunakan plugin jQuery, HUtil , dan menulis antarmuka seperti Sejarah YUI di atasnya.

Lihat sekali. Jika Anda membutuhkan bantuan, saya dapat membantu.

moha297
sumber