Как изменить URL-адрес без перезагрузки страницы?

2381

Есть ли способ изменить URL текущей страницы без перезагрузки страницы?

Я хотел бы получить доступ к части до # хэша, если это возможно.

Мне нужно только изменить часть после домена, поэтому я не нарушаю междоменные политики.

 window.location.href = "www.mysite.com/page2.php";  // Sadly this reloads
Вспышка
источник
139
Просто чтобы облегчить понимание вопроса, это то, что делает Facebook, например, когда вы открываете фотографию. Панель URL-адресов изменится так, чтобы указывать ПРЯМО на эту фотографию, чтобы вы могли поделиться URL-адресом, не теряя своего местоположения на сайте. Помните сайты на основе разработки в прошлом десятилетии? Вы можете получить только URL домашней страницы, потому что менялись только внутренние рамки. И это было ужасно.
Spidey
Хотя history.pushState(), возможно, здесь правильный ответ, в этой ситуации (в зависимости от конкретных обстоятельств ...) возможность использования перенаправления на стороне сервера (например, с помощью директивы Apache RewriteRule) - это то, что вы, возможно, захотите рассмотреть, или, по крайней мере, быть в курсе. Просто подумал, что стоит упомянуть!
Doin

Ответы:

2035

Теперь это можно сделать в 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
Дэвид Мердок
590

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

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

Подробнее об этом читайте здесь

Vivart
источник
12
Может не работать по file:///соображениям безопасности, например, Firefox 30. Проверьте localhostс помощью python -m SimpleHTTPServer.
Сиро Сантилли 法轮功 冠状 病 六四 事件 法轮功
6
Предполагается, что первый параметр будет объектом, а не просто строкой.
Алексис Уилке
40
ИМО это действительно лучший ответ. Если все, что вам нужно, это обновить текущий URL ({}, null, strNewPath), это все, что вам нужно сделать. Лучше всего сначала протестировать с помощью if (history.pushState) {}
Крейг Джейкобс
7
Вы можете просто ввести значение NULL для первых 2 параметров, если вы не хотите их изменять. Вы также можете использовать абсолютный URL для третьего параметра.
Андрей
3
Было бы неплохо, если бы вы добавили больше информации просто в ответ. Я понятия не имею, что делает параметр 1.
RedClover
130

Вы также можете использовать HTML5 replaceState, если вы хотите изменить URL, но не хотите добавлять запись в историю браузера:

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

Это «сломает» функциональность кнопки «назад». Это может потребоваться в некоторых случаях, например, в галерее изображений (где вы хотите, чтобы кнопка «Назад» возвращалась на индексную страницу галереи вместо перемещения назад по каждому просмотренному вами изображению), при этом каждому изображению присваивался уникальный URL-адрес.

Джордж Филиппакос
источник
110

Вот мое решение (newUrl - ваш новый URL, который вы хотите заменить текущим):

history.pushState({}, null, newUrl);
Haimei
источник
1
Лучше всего сначала проверить с if (history.pushState) {} На всякий случай старый браузер.
Крейг Джейкобс
Это больше не работает, вы получите в Firefox: операция небезопасна.
kkatusic
И пользователь может даже установить закладку с таким подходом, красиво! Теперь я могу обновить URL-адрес при вводе пользователем, и он может напрямую добавить в закладки все свои настройки.
Codepleb
107

ПРИМЕЧАНИЕ. Если вы работаете с браузером HTML5, вам следует игнорировать этот ответ. Теперь это возможно, как видно из других ответов.

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

Одной из очевидных причин является то, что вы пишете сайт, www.mysite.comкоторый выглядит как страница входа в банк. Затем вы измените адресную строку браузера, чтобы сказать www.mybank.com. Пользователь будет совершенно не осознавать, что он действительно смотрит www.mysite.com.

Робин Дэй
источник
33
Я не хочу менять домен, только путь и имя файла.
TheFlash
5
Это все еще не останавливает потенциальные угрозы безопасности, так как браузер не знает, что домен / mysite и domain / othersite оба считаются "безопасными" для пользователя. Может быть, вопрос должен быть: почему вы хотите изменить URL? Если это скрывает это от пользователя, вы можете просто запустить свое приложение в iframe.
День Робина
5
Вы можете сделать это с помощью Flash. Это позволит вам изменить URL без запроса. Это возможно, потому что Flash работает вне браузера, но очень тесно с ним.
Ник Берарди
142
Я должен сказать, что есть совершенно веские причины для изменения URL-адреса в адресной строке на стороне клиента. Например, если у вас есть таблица данных с подкачкой, сортировкой и фильтрацией, и вы хотите, чтобы эти вещи работали на Ajax, но при этом обновите URL-адрес, чтобы текущее состояние страницы можно было добавить в закладки. Я могу понять риски безопасности при изменении имени домена (фишинг и т. Д.), Но почему браузеры не позволяют изменять только часть URL-адреса справа от домена верхнего уровня с помощью сценария?
Воскресенье Ironfoot
41
этот ответ уже не на 100% верен. Смотрите мой ответ для деталей.
Дэвид Мердок
83
parent.location.hash = "hello";
Мартин.
источник
15
Я хочу изменить URL, а не только хэш - #mydata
TheFlash
42
Изменение хеша может быть полезно в ajax, так как это своего рода состояние без использования куки, оно доступно для закладки и совместимо с кнопками возврата браузера. 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. Атикур Рахман
Загружайте контент, как вы это обычно делаете с ajax.
AndroidDev
26

HTML5 replaceState - это ответ, как уже упоминалось 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-адрес, и вы не используете хеш-привязки для чего-либо еще, то вы можете сделать это за два части; Вы используете расположение.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/…
Snook
13

Любые изменения локона (или, window.locationили document.location) вызовут запрос на этот новый URL, если вы не просто меняете фрагмент URL. Если вы измените URL, вы измените URL.

Используйте серверные методы перезаписи URL, такие как mod_rewrite в Apache, если вам не нравятся URL, которые вы используете в данный момент.

гумбо
источник
Могу ли я использовать "location.pathname" ??
TheFlash
3
Нет, изменение этого атрибута также вызовет запрос.
Гамбо
11

Вы можете добавить якорные теги. Я использую это на своем сайте, чтобы с помощью Google Analytics отслеживать, что люди посещают на странице.

Я просто добавляю метку привязки, а затем ту часть страницы, которую я хочу отслеживать:

var trackCode = "/#" + urlencode($("myDiv").text());
window.location.href = "http://www.piano-chords.net" + trackCode;
pageTracker._trackPageview(trackCode);
Nate
источник
9

Как указал Томас Стьернегард Джеппезен, вы можете использовать History.js для изменения параметров URL, пока пользователь перемещается по ссылкам и приложениям Ajax.

С тех пор прошел почти год, и History.js вырос и стал более стабильным и кросс-браузерным. Теперь его можно использовать для управления историческими состояниями в HTML5-совместимых, а также во многих браузерах только для HTML4. В этой демонстрации вы можете увидеть пример того, как он работает (а также попробовать его функциональные возможности и ограничения).

Если вам нужна помощь в использовании и реализации этой библиотеки, я предлагаю вам взглянуть на исходный код демонстрационной страницы: вы увидите, что это очень легко сделать.

Наконец, для всестороннего объяснения того, что может быть проблемами с использованием хешей (и hashbangs), проверьте эту ссылку Бенджамином Луптоном.

Эренор Пас
источник
8

Используйте history.pushState()из HTML 5 History API.

Обратитесь к API истории HTML5 для более подробной информации.

Пратамеш Расам
источник
7

Вы можете использовать эту красивую и простую функцию, чтобы в любом месте вашего приложения.

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

Вы можете не только редактировать URL, но и обновлять заголовок вместе с ним.

Довольно полезно всем.

Dheeraj Thedijje
источник
1
Работает как шарм даже для якорейwindow.history.pushState('data', 'Title', '#new_location');
BIOHAZARD