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

Change the URL in the browser without loading the new page using JavaScript

我该如何使用一个javascript操作,该操作可能对当前页面有一些影响,但也会更改浏览器中的URL,因此如果用户点击"重新加载"或"书签",将使用新的URL?

如果后退按钮可以重新加载原始的URL,也会很好。

我正在尝试在URL中记录javascript状态。


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

基本思想是将window.location.hash属性设置为包含您需要的任何状态信息的值,然后使用window.onhashchange事件,或者对于不支持onhashchange的旧浏览器(例如<8,firefox<3.6),定期检查哈希是否已更改(例如使用setInterval并更新页面。您还需要检查页面加载时的哈希值以设置初始内容。

如果您使用的是jquery,那么有一个hashchange插件将使用浏览器支持的任何方法。我相信其他库也有插件。

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


对于HTML5,使用history.pushState函数。举个例子:

1
2
3
4
5
6
7
8
<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);

和一个HREF:

1
Click to change url to bar.html

如果要更改URL而不向后退按钮列表中添加条目,请使用history.replaceState


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

如果您希望在URL中记录javascript状态,以便在不重新加载页面的情况下对其进行书签,请在a之后将其附加到当前URL,并让onload事件触发的一段javascript分析当前URL,以查看它是否包含保存状态。

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


我强烈怀疑这是不可能的,因为如果是的话,这将是一个不可思议的安全问题。例如,我可以创建一个看起来像银行登录页面的页面,并使地址栏中的URL看起来像真正的银行!

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

[2011年编辑:自2008年我写下这个答案以来,更多关于HTML5技术的信息已经曝光,该技术允许修改URL,只要它来自同一个来源]


浏览器安全设置阻止用户直接修改显示的URL。你可以想象网络钓鱼漏洞会导致什么。

更改URL而不更改页面的唯一可靠方法是使用内部链接或哈希。例如:http://site.com/page.html变为http://site.com/page.html item1。这种技术通常用于Hijax(Ajax+保留历史)。

在执行此操作时,我通常只使用以哈希为href的操作的链接,然后使用jquery添加click事件,这些事件使用请求的哈希来确定和委托操作。

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


jquery有一个很好的插件,用于更改浏览器的URL,称为jquery pusher。

javascript pushState和jquery可以一起使用,例如:

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

例子:

1
2
3
4
5
6
7
8
9
10
11
$('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。让我们更详细地检查这三个参数中的每一个:

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

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

  • 标题-火狐目前忽略了这个参数,尽管将来可能会用到它。在这里传递空字符串应该是安全的,以防将来对方法进行更改。或者,您可以为要移动到的状态传递一个简短的标题。

  • url-新历史记录条目的url由该参数提供。请注意,浏览器在调用pushState()后不会尝试加载此URL,但稍后可能会尝试加载此URL,例如在用户重新启动浏览器后。新的URL不需要是绝对的;如果它是相对的,那么它是相对于当前的URL解析的。新的URL必须与当前的URL具有相同的来源;否则,pushState()将引发异常。此参数是可选的;如果未指定,则将其设置为文档的当前URL。


  • 有一个yahoo yui组件(浏览器历史管理器)可以处理这个问题:http://developer.yahoo.com/yui/history/


    Facebook的照片库使用URL中的哈希来完成此操作。以下是一些URL示例:

    单击"下一步"之前:

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

    单击"下一步"后:

    1
    /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

    注意散列键(!)紧接着是新的URL。


    我的工作是-history.replaceState()功能,如下所示-

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

    这不会重新加载页面,您可以将其与JavaScript事件一起使用。


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

    我想这就是你需要的。


    我的代码是:

    1
    2
    3
    4
    5
    6
    7
    8
    //change address bar
    function setLocation(curLoc){
        try {
            history.pushState(null, null, curLoc);
            return false;
        } catch(e) {}
            location.hash = '#' + curLoc;
    }

    行动:

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

    举例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $(document).ready(function(){
        $('nav li a').on('click', function(){
            if($(this).hasClass('active')) {

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

    就是这样:


    我想知道,只要页面中的父路径相同,是否可以设置它的位置,只有一些新的内容被附加到它上面。

    比如说用户在页面: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页面中的后退和前进按钮能够缓存数据,并且不会花时间重新加载数据。

    据我所见,雅虎的历史记录已经一次加载了所有的数据。它似乎没有执行任何Ajax请求。因此,当使用div来处理不同的方法超时时,不会为每个历史状态存储数据。


    一个更简单的答案,

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

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


    我在以下方面取得了成功:

    1
    location.hash="myValue";

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

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