改变 URL 地址而不重定向?

可能的复制品:
修改 AJAX 应用程序中的地址栏 URL 以匹配当前状态

如何在不重定向页面的情况下更改 URL 地址?

例如,当我点击下面的链接:

<a href="http://mysite.com/projects/article-1" class="get-article">link</a>

我将从链接中获取网址:

var path = object.attr('href');

如果我在下面这样做,页面将被重定向:

window.location = path;

我想做一些像这样的 工地,当你点击图像,Ajax 调用将获取所请求的页面和窗口上的 URL 地址也将改变,以便它有一个路径为您点击。

187334 次浏览

That site makes use of the "fragment" part of a url: the stuff after the "#". This is not sent to the server by the browser as part of the GET request, but can be used to store page state. So yes you can change the fragment without causing a page refresh or reload. When the page loads, your javascript reads this fragment and updates the page content appropriately, fetching data from the server via ajax requests as required. To read the fragment in js:

var fragment = location.hash;

but note that this value will include the "#" character at the beginning. To set the fragment:

location.hash = "your_state_data";

No, because that would open up the floodgates for phishing. The only part of the URI you can change is the fragment (everything after the #). You can do so by setting window.location.hash.

You cannot really change the whole URL in the location bar without redirecting (think of the security issues!).

However you can change the hash part (whats after the #) and read that: location.hash

ps. prevent the default onclick redirect of a link by something like:

$("#link").bind("click",function(e){
doRedirectFunction();
e.preventDefault();
})

You can't do what you ask (and the linked site does not do exactly that either).

You can, however, modify the part of the url after the # sign, which is called the fragment, like this:

window.location.hash = 'something';

Fragments do not get sent to the server (so, for example, Google itself cannot tell the difference between http://www.google.com/ and http://www.google.com/#something), but they can be read by Javascript on your page. In turn, this Javascript can decide to perform a different AJAX request based on the value of the fragment, which is how the site you linked to probably does it.

This is achieved through URL rewriting, not through URL obfuscating, which can't be done.

Another way to do this, as has been mentioned is by changing the hashtag, with

window.location.hash = "/2131/"

NOTE: history.pushState() is now supported - see other answers.

You cannot change the whole url without redirecting, what you can do instead is change the hash.

The hash is the part of the url that goes after the # symbol. That was initially intended to direct you (locally) to sections of your HTML document, but you can read and modify it through javascript to use it somewhat like a global variable.


If applied well, this technique is useful in two ways:

  1. the browser history will remember each different step you took (since the url+hash changed)
  2. you can have an address which links not only to a particular html document, but also gives your javascript a clue about what to do. That means you end up pointing to a state inside your web app.

To change the hash you can do:

document.location.hash = "show_picture";

To watch for hash changes you have to do something like:

window.onhashchange = function(){
var what_to_do = document.location.hash;
if (what_to_do=="#show_picture")
show_picture();
}

Of course the hash is just a string, so you can do pretty much what you like with it. For example you can put a whole object there if you use JSON to stringify it.

There are very good JQuery libraries to do advanced things with that.

See here - http://my.opera.com/community/forums/topic.dml?id=1319992&t=1331393279&page=1#comment11751402

Essentially:

history.pushState('data', '', 'http://your-domain/path');

You can manipulate the history object to make this work.

It only works on the same domain, but since you're satisfied with using the hash tag approach, that shouldn't matter.

Obviously would need to be cross-browser tested, but since that was posted on the Opera forum I'm safe to assume it would work in Opera, and I just tested it in Chrome and it worked fine.