在不使用JavaScript加载新页面的情况下更改浏览器中的URL

时间:2008-09-25 22:00:39

标签: javascript url fragment-identifier hashchange

我如何对当前页面产生某些影响的JavaScript操作,但也会更改浏览器中的URL,以便在用户点击重新加载或书签时使用新的URL?

如果后退按钮会重新加载原始网址也会很好。

我正在尝试在网址中记录JavaScript状态。

14 个答案:

答案 0 :(得分:187)

如果您希望它在不支持history.pushStatehistory.popState的浏览器中工作,那么“旧”方式是设置片段标识符,这不会导致页面重新加载。

基本思想是将window.location.hash属性设置为包含所需状态信息的值,然后使用window.onhashchange event或不支持{{1}的旧版浏览器(IE< 8,Firefox< 3.6),定期检查散列是否已更改(例如,使用onhashchange)并更新页面。您还需要检查页面加载时的哈希值以设置初始内容。

如果您正在使用jQuery,那么hashchange plugin将使用浏览器支持的任何方法。我确信其他库也有插件。

要注意的一件事是与页面上的ID冲突,因为浏览器将滚动到任何具有匹配ID的元素。

答案 1 :(得分:113)

使用HTML 5,使用history.pushState function。举个例子:

<script type="text/javascript">
var stateObj = { foo: "bar" };
function change_my_url()
{
   history.pushState(stateObj, "page 2", "bar.html");
}
var link = document.getElementById('click');
link.addEventListener('click', change_my_url, false);
</script>

和一个href:

<a href="#" id='click'>Click to change url to bar.html</a>

如果您想更改网址而不在后退按钮列表中添加条目,请改用history.replaceState

答案 2 :(得分:37)

window.location.href包含当前的URL。你可以从中读取,你可以附加它,你可以替换它,这可能会导致页面重新加载。

如果听起来像是想要在URL中记录javascript状态,以便可以将其加入书签,而无需重新加载页面,请在#之后将其附加到当前URL,并使用onload事件触发一段javascript解析当前URL以查看它是否包含已保存的状态。

如果使用?而不是#,你将强制重新加载页面,但由于你将在加载时解析保存的状态,这实际上可能不是一个问题;这将使前进和后退按钮也能正常工作。

答案 3 :(得分:22)

我强烈怀疑这是不可能的,因为如果它是一个令人难以置信的安全问题。例如,我可以创建一个看起来像银行登录页面的页面,并使地址栏中的URL看起来就像真实银行一样

也许如果你解释为什么要这样做,人们可能会建议其他方法......

[编辑于2011年:自从我在2008年撰写此答案以来,有关HTML5 technique的更多信息已经曝光,只要它来自同一个来源,就可以修改网址。 / em>的

答案 4 :(得分:8)

浏览器安全设置可防止用户直接修改显示的网址。您可以想象可能导致的网络钓鱼漏洞。

只有在不更改页面的情况下更改网址的可靠方法是使用内部链接或哈希。例如:http://site.com/page.html变为http://site.com/page.html#item1。这种技术通常用于hijax(AJAX +保存历史)。

执行此操作时,我通常只使用带有散列的操作的链接作为href,然后使用jquery添加单击事件,使用请求的散列来确定和委派操作。

我希望这会让你走上正确的道路。

答案 5 :(得分:7)

jQuery 有一个很棒的插件,用于更改浏览器的网址,名为 jQuery-pusher

JavaScript pushState和jQuery可以一起使用,例如:

history.pushState(null, null, $(this).attr('href'));

示例:

$('a').click(function (event) {

  // Prevent default click action
  event.preventDefault();     

  // Detect if pushState is available
  if(history.pushState) {
    history.pushState(null, null, $(this).attr('href'));
  }
  return false;
});


仅使用更改引用者的 JavaScript history.pushState(),在更改状态后创建的XMLHttpRequest对象的HTTP标头中使用。

示例:

window.history.pushState("object", "Your New Title", "/new-url");

pushState()方法:

pushState()有三个参数:状态对象,标题(当前被忽略)和(可选)URL。让我们更详细地研究这三个参数中的每一个:

  1. 状态对象 - 状态对象是一个JavaScript对象,它与pushState()创建的新历史记录条目相关联。只要用户导航到新状态,就会触发popstate事件,并且事件的state属性包含历史记录条目的状态对象的副本。

    state对象可以是任何可以序列化的对象。因为Firefox将状态对象保存到用户的磁盘,因此可以在用户重新启动浏览器后恢复它们,因此我们在状态对象的序列化表示上强加了640k字符的大小限制。如果将序列化表示形式大于此的状态对象传递给pushState(),则该方法将引发异常。如果您需要更多空间,建议您使用sessionStorage和/或localStorage。

  2. title - Firefox目前会忽略此参数,但将来可能会使用它。在此处传递空字符串应该可以安全地防止将来对方法进行更改。或者,您可以为您要移动的州通过一个简短的标题。

  3. URL - 此参数给出了新历史记录条目的URL。请注意,在调用pushState()后,浏览器不会尝试加载此URL,但稍后可能会尝试加载URL,例如在用户重新启动浏览器之后。新URL不一定是绝对的;如果是相对的,则相对于当前URL进行解析。新网址必须与当前网址的来源相同;否则,pushState()将抛出异常。此参数是可选的;如果未指定,则将其设置为文档的当前URL。

答案 6 :(得分:4)

有一个Yahoo YUI组件(浏览器历史记录管理器)可以处理:http://developer.yahoo.com/yui/history/

答案 7 :(得分:3)

Facebook的照片库使用网址中的#hash执行此操作。以下是一些示例网址:

点击“下一步”之前:

/photo.php?fbid=496429237507&set=a.218088072507.133423.681812507&pid=5887027&id=681812507

点击“下一步”后:

/photo.php?fbid=496429237507&set=a.218088072507.133423.681812507&pid=5887027&id=681812507#!/photo.php?fbid=496435457507&set=a.218088072507.133423.681812507&pid=5887085&id=681812507

请注意hash-bang(#!)后面紧跟新网址。

答案 8 :(得分:2)

有一个jquery插件http://www.asual.com/jquery/address/

我认为这就是你所需要的。

答案 9 :(得分:2)

对我有用的是 - history.replaceState()功能,如下所示 -

history.replaceState(data,"Title of page"[,'url-of-the-page']);

这不会重新加载页面,你可以使用它与javascript事件

答案 10 :(得分:1)

我想知道只要页面中的父路径相同,它是否可行,只会附加一些新内容。

就像让我们说用户在页面上一样:http://domain.com/site/page.html 然后浏览器可以让我location.append = new.html 页面变为:http://domain.com/site/page.htmlnew.html,浏览器不会更改它。

或者只是允许此人更改get参数,所以让我们location.get = me=1&page=1

因此原始页面变为http://domain.com/site/page.html?me=1&page=1并且不会刷新。

#的问题是当哈希值发生变化时,数据不会被缓存(至少我不这么认为)。因此,就像每次加载新页面一样,而非Ajax页面中的后退和前进按钮能够缓存数据,而不会花时间重新加载数据。

从我看到的情况来看,Yahoo历史事件已经一次加载了所有数据。它似乎没有做任何Ajax请求。因此,当div用于处理超时的不同方法时,不会为每个历史状态存储该数据。

答案 11 :(得分:1)

我的代码是:

//change address bar
function setLocation(curLoc){
    try {
        history.pushState(null, null, curLoc);
        return false;
    } catch(e) {}
        location.hash = '#' + curLoc;
}

和行动:

setLocation('http://example.com/your-url-here');

和示例

$(document).ready(function(){
    $('nav li a').on('click', function(){
        if($(this).hasClass('active')) {

        } else {
            setLocation($(this).attr('href'));
        }
            return false;
    });
});

这就是全部:)

答案 12 :(得分:0)

我成功了:

location.hash="myValue";

它只是将#myValue添加到当前网址。如果您需要在页面加载时触发事件,则可以使用相同的location.hash来检查相关值。请记住从#返回的值中移除location.hash,例如

var articleId = window.location.hash.replace("#","");

答案 13 :(得分:0)

我提出的一个更简单的答案

window.history.pushState(null, null, "/abc")

这将在浏览器URL中的域名之后添加/abc。只需复制此代码并将其粘贴到浏览器控制台中,即可看到URL更改为“ https://stackoverflow.com/abc