On - window.location.hash - Змінити?


558

Я використовую Ajax і хеш для навігації.

Чи є спосіб перевірити, чи window.location.hashзмінилися так?

http://example.com/blah №123 до http://example.com/blah # 456

Він працює, якщо я перевіряю його, коли документ завантажується.

Але якщо у мене навігація на основі #hash, вона не працює, коли натискаю кнопку "назад" у браузері (тому я переходжу з бла № 456 на бла №123).

Він відображається всередині адресного поля, але я не можу впіймати його JavaScript.


6
Оформити цей плагін jquery: github.com/cowboy/jquery-hashchange
Xavi

9
History.js підтримує функціональність управління державою HTML5 (тому вам більше не потрібно використовувати хеші!) І витончено знижує його до браузерів HTML4 за допомогою хеш-змін. Він підтримує jQuery, MooTools та Prototype поза коробкою.
balupton

@balupton, насправді нам все-таки потрібно використовувати хеші для надання відгуку користувачеві про те, що "нова сторінка" була вставлена ​​в його історію, якщо ви не використовуєте зміну URL-адреси як відгук.
Пейсьєр


хм ... я думаю, що вам потрібен moar jQuery
RaisingAgent

Відповіді:


617

Єдиний спосіб насправді зробити це (і як це робить «дійсно простою історією») - це встановити інтервал, який продовжує перевіряти поточний хеш, і порівнюючи його з тим, що було раніше, ми робимо це і дозволяємо абонентам підписатися на змінене подія, яку ми запускаємо, якщо хеш змінюється .. його не ідеально, але браузери справді не підтримують цю подію.


Оновіть, щоб ця відповідь була свіжою:

Якщо ви використовуєте jQuery (що сьогодні для більшості має бути дещо фундаментальним), то приємним рішенням є використання абстракції, яку дає вам jQuery, використовуючи систему подій для прослуховування подій хеш-зміни на об’єкт вікна.

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

Приємно, що ви можете написати код, який не потребує навіть турбуватися про підтримку хеш-обміну, проте вам НЕ потрібно робити магію, у вигляді дещо менш відомої функції jQuery особливих подій jQuery .

Завдяки цій функції ви, по суті, отримуєте запустити деякий код налаштування будь-якої події, коли перший раз хтось намагається використати подію будь-яким способом (наприклад, прив'язкою до події).

У цьому коді налаштування ви можете перевірити підтримку нативної веб-переглядача, і якщо браузер не реалізує це, ви можете встановити один таймер для опитування змін та запустити подію jQuery.

Це повністю скасовує ваш код від необхідності розуміння цієї проблеми підтримки, реалізація спеціальної подібної події є тривіальною (щоб отримати просту 98% працюючу версію), але навіщо це робити, коли хтось уже має .


7
IE8 робить. Більше прибути
Сергію Іллінський

28
Найновіша збірка Firefox (3,6 альфа) також тепер підтримує вбудовану подію змінити хеш: developer.mozilla.org/en/DOM/window.onhashchange Напевно варто перевірити цю подію, але зауважте, що IE8 повідомить вам про подію існує, коли він працює в режимі співвідношення IE7 .. на жаль, подія не спрацьовує. Вам потрібно перевірити подію і чи не виглядає браузер IE7 .. зітхнення (або спроба викликати подію методом IE fireEvent).
meandmycode

8
На момент написання повідомлення WebKit також запускає hashchangeподію, а Safari (стабільний) ще не робить.
jholster

51
Просто щоб додати ще одне оновлення, то hashchangeподія в даний час широко підтримується: caniuse.com/#search=hash
Paystey

19
Чи я єдиний, хто думає, що незапрошені відповіді jQuery - це біль?
Люк

290

HTML5 визначає hashchangeподію . Зараз ця подія підтримується всіма сучасними браузерами . Підтримка додана в наступних версіях браузера:

  • Internet Explorer 8
  • Firefox 3.6
  • Chrome 5
  • Сафарі 5
  • Опера 10.6

20
Оновлення: FF 5, Safari 5 та Chrome 12 підтримують цю подію станом на червень 2011 року
james.garriss

2
Ось сторінка CanIUse для хеш-зміни . Ось хеш-обмін на quirksmode . Підтримка IE є невдалою щодо чутливості до справ.
Тобу

3
@everybody, не потрібно продовжувати додавати відповідь у розділі коментарів - саме для цього потрібна кнопка "Редагувати". :)
Майкл Мартін-Смукер

15
використання:window.onhashchange = function() { doYourStuff(); }
Кріс

4
Документація MDN про подію хеш-змін .
Dabowheel

52

Зауважте, що у випадку Internet Explorer 7 та Internet Explorer 9 ifвідмітка відповідає справжньому (для "onhashchange" у windows), але window.onhashchangeніколи не запуститься, тому краще зберігати хеш і перевіряти його після кожні 100 мілісекунд, змінився він чи ні для всіх версій 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 - Оскільки jQuery 1.9, $.browser.msieне підтримується. Джерело: http://api.jquery.com/jquery.browser/


14

Існує маса хитрощів для вирішення історії та window.location.hash у браузерах IE:

  • Як було сказано в оригінальному запитанні, якщо перейти зі сторінки a.html # b до a.html # c, а потім натиснути кнопку назад, браузер не знає, що ця сторінка змінилася. Дозвольте сказати це на прикладі: window.location.href буде "a.html # c", незалежно від того, чи перебуваєте ви в a.html # b або a.html # c.

  • Власне, a.html # b та a.html # c зберігаються в історії лише за умови, що елементи "<a name="#b">" та "<a name="#c">" раніше існують на сторінці.

  • Однак якщо ви вставите кадр iframe всередині сторінки, перейдіть від a.html # b до a.html # c у цьому iframe, а потім натисніть кнопку назад, якщо iframe.contentWindow.document.location.href зміниться, як очікувалося.

  • Якщо ви використовуєте у своєму коді "document.domain = щось ", ви не можете отримати доступ до iframe.contentWindow.document.open () "(і це робить багато менеджерів історії)

Я знаю, що це не реальна відповідь, але, можливо, примітки IE-історії комусь корисні.



11

У Бен Альмана є чудовий плагін jQuery для вирішення цього питання: http://benalman.com/projects/jquery-hashchange-plugin/

Якщо ви не використовуєте jQuery, це може бути цікавою посиланням на розсічення.


Плагін Ben Alman, здається, більше не підтримується. Хоча є кілька вилок.
Mnebuerquo

9

Ви можете легко реалізувати спостерігача (метод "спостерігати") за властивістю "хеш" об'єкта "window.location".

Firefox має власну реалізацію для перегляду змін об’єкта , але якщо ви використовуєте якусь іншу реалізацію (наприклад, Перегляд змін об’єктів властивостей у JavaScript ) - для інших браузерів, це зробить трюк.

Код буде виглядати приблизно так:

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

Тоді ви можете протестувати:

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

І звичайно, це запустить вашу функцію спостерігача.


Краще використовувати: window.location.href замість window.location.
Codebeat

3
Він дивиться window.location.hash, а не window.location.
визначено

1
@BrianMortenson: згідно з документами ( developer.mozilla.org/en-US/docs/JavaScript/Reference/… ) ви повинні застосувати watchдо об'єкта, який володіє властивістю, яке змінюється, і ви хочете його спостерігати.
gion_13

@ gion_13 Так, саме це я намагався вказати. Під «Він» я мав на увазі вас, і це було спрямовано на коментар Ервіна. Я повинен був бути більш чітким. Дякуємо за Ваш уточнюючий коментар.
визначено

7

Я використовував це в додатку для реагування, щоб зробити відображення URL-адрес різними параметрами залежно від того, на якому режимі переглядає користувач.

Я переглянув хеш-параметр, використовуючи

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

Тоді

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

Працював частування, працює з кнопками браузера вперед і назад, а також в історії браузера.


1
у своєму addEventListenerдзвінку ви повинні зняти ()зdoSomethingWithChangeFunction
Jason S

Чи можете ви надати причину для видалення ()? Я знаю, що це буде працювати з будь-яким, і менше коду є здебільшого кращим варіантом, але це здається прискіпливим, якщо немає поважних причин підкріпити це?
Sprose

6
? це не повинно працювати (). addEventListenerФункція вимагає, щоб передати в функцію. doSomethingWithChangeFunctionє функцією. doSomethingWithChangeFunction()- це повернене значення тієї функції, яке в даному випадку не є функцією.
Джейсон S

6

Гідну реалізацію можна знайти на веб- сторінці http://code.google.com/p/reallysimplehistory/ . Єдина (але також) проблема та помилка, це: в Internet Explorer, змінивши хеш розташування вручну, буде скинутий весь стек історії (це проблема браузера, і її неможливо вирішити).

Зауважте, що в Internet Explorer 8 є підтримка події "хешхек", і оскільки він стає частиною HTML5, ви можете очікувати, що інші браузери зможуть наздогнати.


1

Ще однією чудовою реалізацією є історія jQuery, яка буде використовувати вбудовану подію onhashchange, якщо вона підтримується браузером, якщо ні, то вона буде використовувати відповідний iframe або інтервал належним чином для браузера, щоб забезпечити успішно емуляцію всіх очікуваних функцій. Він також забезпечує приємний інтерфейс для прив’язки до певних станів.

Ще один проект, який варто відзначити, - це jQuery Ajaxy, який в значній мірі є розширенням для історії jQuery, щоб додати ajax до суміші. Як коли ви починаєте використовувати Ajax з хешами, це стає досить складно !


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

Це все ... тепер, коли ви натискаєте кнопку назад або назад, сторінка буде перезавантажена відповідно до нового значення хешу.


не використовуйте рядки eval
Vitim.us

1

Я використовую path.js для маршрутизації на стороні свого клієнта. Я виявив, що це досить лаконічний і легкий (він також був опублікований в NPM) і використовує навігацію на основі хешу.

path.js NPM

path.js GitHub


0

Я використовував плагін jQuery, HUtil , і написав історію YUI, як інтерфейс поверх нього.

Перевірте це один раз. Якщо вам потрібна допомога, я можу допомогти.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.