Як змінити URL-адресу, не завантажуючи сторінку?


2376

Чи можна змінити URL-адресу поточної сторінки, не завантажуючи сторінку?

Я хотів би отримати доступ до порції до # хеша, якщо це можливо.

Мені потрібно змінити лише частину після домену, так що це не так, як я порушую політику між доменними.

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

139
Просто для того, щоб легше зрозуміти питання, це те, що робить Facebook, наприклад, коли ви відкриваєте фотографію. Рядок URL-адреси змінюється, щоб НАПРЯМО вказувати на цю фотографію, тому ви можете ділитися URL-адресою, не втрачаючи місця, де ви знаходитесь на сайті. Пам’ятаєте сайти, засновані на обрамленні минулого десятиліття? Ви можете отримати лише URL-адресу домашньої сторінки, оскільки змінювались лише внутрішні кадри. І це було жахливо.
Spidey

Хоча history.pushState()тут, мабуть, правильна відповідь, але в цій ситуації (залежно від конкретних обставин ...) можливість використання перенаправлення на стороні сервера (наприклад, за допомогою директиви RewriteRule Apache) - це те, що ви могли б хотіти розглянути, або принаймні бути в курсі. Просто думав, що це слід згадати!
Зробіть

Відповіді:


2032

Тепер це можна зробити в 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?
Домінік

57
@CHiRiLo ознайомтеся з history.js, що забезпечує резервну копію для браузерів, які не підтримують API історії HTML5.
Девід Мердок

23
@infensus Якщо в URL-адресі десь є знак #, ця хитрість існує роками ..
Izkata

34
Що означає "pp4 +" частина "IE10pp4 +"?
Скотт Теслер

34
попередній перегляд платформи 4
Девід Мердок

585

HTML5 представив history.pushState()і history.replaceState()методи, які дозволяють додавати та змінювати записи історії відповідно.

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

Детальніше про це читайте тут


12
Може не працювати по file:///причин безпеки, наприклад , Firefox 30. Тест на localhostз python -m SimpleHTTPServer.
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

6
Перший параметр, як очікується, буде об'єктом, а не просто рядком.
Алексіс Вілке

40
ІМО це справді найкраща відповідь. Якщо все, що вам потрібно зробити, це оновити поточну URL-адресу ({}, null, strNewPath) - все, що вам потрібно зробити. Найкраще спершу тестувати, якщо (history.pushState) {}
Крейг Джейкобс

7
ви можете просто ввести null для перших 2 параметрів, якщо ви не хочете їх змінювати. Ви також можете використовувати абсолютний URL для третього параметра.
Андрій

3
Було б непогано, якщо ви додасте ще трохи інформації у відповідь. Я не маю уявлення, що робить параметр 1.
RedClover

129

Ви також можете використовувати HTML5 substituState, якщо ви хочете змінити URL-адресу, але не хочете додавати запис до історії браузера:

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

Це призведе до "порушення" функціональності кнопки "назад". Це може знадобитися в деяких випадках, наприклад, у галереї зображень (де ви хочете, щоб кнопка "Назад" поверталася назад на сторінку покажчика галереї, а не переміщувалася назад через кожне зображення, яке ви переглядали), надаючи кожному зображенню свою унікальну URL-адресу.


109

Ось моє рішення (newUrl - це ваша нова URL-адреса, яку ви хочете замінити на поточну):

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

1
Найкраще спершу перевірити, якщо (history.pushState) {} Про всяк випадок, коли старий браузер.
Крейг Джейкобс

Це більше не працює, ви отримаєте у Firefox: Операція небезпечна.
kkatusic

І користувач навіть може встановити закладку при такому підході, красиво! Тепер я можу оновити URL на введенні користувача, і він може безпосередньо робити закладку незалежно від його налаштувань.
codepleb

106

ПРИМІТКА. Якщо ви працюєте з браузером HTML5, вам слід проігнорувати цю відповідь. Це зараз можливо, як видно з інших відповідей.

Немає можливості змінити URL-адресу в браузері без перезавантаження сторінки. URL-адреса представляє останню завантажену сторінку. Якщо змінити його ( document.location), він перезавантажить сторінку.

Очевидно, що ви пишете веб-сайт www.mysite.com, схожий на сторінку входу в банк. Потім ви змінюєте URL-адресу браузера, щоб сказати www.mybank.com. Користувач буде абсолютно невідомий, що він дійсно дивиться www.mysite.com.


33
Я не хочу змінювати домен, лише шлях та ім'я файлу.
TheFlash

5
Це все ще не зупиняє потенційні ризики для безпеки, оскільки браузер не має уявлення, що домен / mysite та домен / othersite обидва вважаються користувачем "безпечними". Можливо, питання має бути, чому ви хочете змінити URL-адресу? Якщо це потрібно приховати від користувача, ви можете просто запустити свою програму в межах рамки.
День Робіна

5
Насправді це можна зробити за допомогою Flash. Це дозволить вам змінити URL-адресу, не роблячи запиту. Це можливо, оскільки Flash працює поза браузером, але дуже щільно з ним.
Нік Берарді

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

41
ця відповідь вже не на 100% правдива. Детальну інформацію див. У моїй відповіді.
Девід Мердок

83
parent.location.hash = "hello";

15
Я хочу змінити URL-адресу, а не тільки хеш - #mydata
TheFlash

42
Зміна хешу може бути корисною в ajax, оскільки це своєрідний стан без використання файлів cookie, є закладкою і сумісний із кнопками повернення браузера. Gmail використовує це сьогодні, щоб зробити його більш зручним для браузера.
Метью Лок

@Jarvis: в чому різниця?
шумно

@noisy Відстеження на стороні Сервера не може бачити хеші, якщо явно не надіслано службі відстеження.
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, що не перезавантажте сторінку. Ось такий спосіб Angular використовує робити SPA відповідно до хештегів ...

Зміна #досить проста, виконуючи такі дії:

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

HTMLS substituState - це відповідь, про що вже згадували 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/…
Снук

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

Як вказував Томас Стєрнеґарда Джеппесен, ви можете використовувати History.js для зміни параметрів URL, в той час як користувач переходить по вашим посиланням та додаткам Ajax

З цього часу минуло майже рік, і History.js зростав та став стабільнішим та переглядачем. Тепер він може використовуватися для управління станами історії як у сумісних з HTML5, так і у багатьох браузерах, що лише HTML4. У цьому демонстраційному описі ви можете побачити приклад того, як це працює (а також можливість спробувати його функціональні можливості та межі.

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

Нарешті, для вичерпного пояснення того, що може бути проблемою щодо використання хешів (та хеш-багів), перегляньте це посилання від Бенджаміна Люптона.



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