Як змінити 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.