pushState()和popState():操纵浏览器的历史 [英] pushState() and popState(): manipulating browsers' history
问题描述
我正在开发一个小项目,我想在其中创建一个Ajax风格的网站。内容使用jQuery的 load()
加载。正如你们中的一些人所知,这样做的缺点是URL不会相应地改变显示的内容。要完成这项工作,您可以使用 pushState()
。由于这不支持跨浏览器,因此我使用插件 history.js
。
这是可行的相当好,但问题是我的后退和前进按钮不能正常工作,我不知道我做错了什么。 URL正在正确更改,内容也是如此,但标题根本没有变化。对于标题,我的意思是显示为浏览器窗口的窗口(或标签)的标题。即加载页面的< title>
或引用该页面的链接的标题属性(它们是相同的)。我认为这与我只呼叫我需要标题的一部分页面(即向载入中添加
)。我仍然想要那个页面的标题。这是我迄今为止所做的一个测试案例。 (自2013年12月28日起不再提供)。jQuery文件: #content
)的事实有关()
$(document).ready(function(){
var firstLink = $(ul> li:first-child> a);
var menuLink = $(ul> li> a);
var firstLoadedHtml = firstLink.attr(href)+#content;
$(#sectionContainer)。hide()。load(firstLoadedHtml).fadeIn(fast);
firstLink.addClass(active);
menuLink.click(function(e){
history.pushState(null,null,this.href);
e.preventDefault();
e.stopImmediatePropagation();
var CurLink = $(this);
var newLoadedHtml = CurLink.attr(href)+ #content;
var oldSection = $(。contentPage);
$(#sectionContainer)。hide()。load(newLoadedHtml).fadeIn(fast );
menuLink.removeClass(active);
CurLink.addClass(active);
});
$(window).bind( 'popstate',函数( ){
var returnLocation = history.location || document.location;
$('#sectionContainer')。load(returnLocation +#content);
});
});
我还注意到,当回到基本页面(即/ sectionLoaderTest /)时,它变为空白一段时间后,仅在一段时间后加载第一页的内容。有没有办法优化它?
此外,我使用jQuery将一个活动类添加到已被单击的链接。我怎样才能确保这个变化相应的历史?因此,当用户导航返回时,正确的链接会突出显示。
因此,这三个问题是:
$ ol b $ b
所有帮助都欢迎您!
$ b 1 :我想建立在history.js和我自己的脚本上,并继续支持< HTML5
浏览器。我更喜欢这个因为1.我知道这必须起作用,有些事情会出错。 2.如果我能看到自己的解决方案并在我已经写过的脚本中实现它,而不是找出一个全新的脚本,那将节省时间。
$ b
注2 :赏金只会给予他或她谁可以回答我所有的问题(3)!
> 回答1 - 在前进和后退时获得标题
据我了解,您希望将文档标题html从链接加载在一个div中。当您通过jQuery .load
在div中加载文件时,您只需在其中输入ajax请求后插入完整的响应文本。因此,所有不应该在div中的东西,如 title
或 meta
标记。然而,当前文档的标题( http://bramvanroy.be/sectionLoaderTest/index.html
)在 title
它位于头部
标记内,而不在
那么我该如何解决它?
好问题,因为 div
元素中的标题
元素是无效的,所以大多数浏览器都会删除它,所以你不能使用这个:
document.title = $(#sectionContainer title)。text();
因为 title
元素可能不存在。
所以我们需要的是来自jQuery .load
函数的直接响应。我可以通过向函数添加回调参数来获得它:
$(#sectionContainer)
.hide ()
.load(newLoadedHtml,function(responseText){
document.title = $(responseText).filter(title).text();
})
.fadeIn( 快);
你可能不明白为什么我使用 .filter
而不是 .find
函数。这是因为jQuery是一种解析 html
, head
和 body $ c $
答案2 - 优化主页的加载时间
文档从顶部到底部加载。
所以首先,CSS,JavaScript等应该是加载然后是主文档。
因为jQuery总是在执行之前等待文档,所以将所有脚本
元素放在主体结束之前并不是一个坏主意,所以你的HTML可以加载之前。
BtW我刚刚遇到了这个问题,所有东西都被缓存了,文档加载非常快。 p>
答案3 - 在前进和后退时修复主动类
说循环通过 a
元素的 href
属性并将其与历史记录中的数据进行比较.getState()
。应该很简单。
您在代码中犯了一些错误 - 您的固定代码:
您将哈希 #content
附加到所有网址中。它没有任何意义,它会再次被jQuery删除:https://github.com/jquery/jquery/blob/master/src/ajax.js#L617 (来自行:158,190,337,617 - rhash在行6)
$(document).ready(function (){
var firstLink = $(ul> li:first-child> a);
var menuLink = $(ul> li> a);
var firstLoadedHtml = firstLink.attr(href);
$(#sectionContainer)。hide()。load(firstLoadedHtml).fadeIn(fast);
firstLink .addClass(active);
menuLink.click(function(e){
e.preventDefault();
e.stopImmediatePropagation();
var newLoadedHtml = $(this).attr(href);
His tory.pushState(null,newLoadedHtml,newLoadedHtml);
$(#sectionContainer)
.hide()
.load(newLoadedHtml,function(responseText){
document.title = $(responseText)。 filter(title).text();
})
.fadeIn(fast);
});
History.Adapter.bind(window,statechange,function(){
menuLink.removeClass(active);
$(a [href =' + History.getState()。title +'])。addClass(active);
$('#sectionContainer')。load(document.location.href,function(responseText){
document.title = $(responseText).filter(title).text();
});
});
});
I am working on a small project in which I want to create an Ajax-style website. Content is loaded with jQuery's load()
. As some of you know, the down side of this is that the URL does not change accordingly to the content that is displayed. To make this work you can use pushState()
. Because this is not cross-browser supported, I used the plug-in history.js
.
This is working quite nicely, but the problem is that my back and forward buttons are not working as they should and I have no idea what I am doing wrong. The URL is changing correctly and the content is as well, but the title is not changing at all. With title I mean what is shown as title of the window (or tab) of the browser window. I.e. the <title>
of the page that is loaded OR the title attribute of the link that refers to that page (they are the same). I think it has to do with the fact that I call only a section of the page whose title I need (i.e. by adding #content
to the load()
). I still want the title of that page though. Here is a test case of what I have up to now. (Not available any more since 28 Dec. 2013.) jQuery file:
$(document).ready(function () {
var firstLink = $("ul > li:first-child > a");
var menuLink = $("ul > li > a");
var firstLoadedHtml = firstLink.attr("href") + " #content";
$("#sectionContainer").hide().load(firstLoadedHtml).fadeIn("fast");
firstLink.addClass("active");
menuLink.click(function(e) {
history.pushState(null, null, this.href);
e.preventDefault();
e.stopImmediatePropagation();
var CurLink = $(this);
var newLoadedHtml = CurLink.attr("href") + " #content";
var oldSection = $(".contentPage");
$("#sectionContainer").hide().load(newLoadedHtml).fadeIn("fast");
menuLink.removeClass("active");
CurLink.addClass("active");
});
$(window).bind('popstate', function() {
var returnLocation = history.location || document.location;
$('#sectionContainer').load(returnLocation + "#content");
});
});
I also noted that when going back to the basic page (i.e. /sectionLoaderTest/) it goes blank for a while and only after a while the content of the first page is loaded. Is there a way to optimize this?
Additionally, I am using jQuery to add an active-class to the link that has been clicked. How can I make sure that this changes accordingly to the history? So that the correct link is highlighted when a user navigates back?
So the three questions are:
- Get the title working when going forward and backward
- Optimize the load time of the mainpage
- Fix the active-class when going forward and backward
All help welcome!
NOTE 1: I would like to build on history.js and my own script and as such keep support for < HTML5
browsers. I would prefer this because 1. I know this has to work, there is just something that's going wrong. 2. It would save time if I could see one's solution and implement it in the script I already wrote rather than figuring out a whole new script.
NOTE 2: The bounty will only be given to he or she who can answer all of my questions (3)!
Answer 1 - Get the title working when going forward and backward
As far as I understood you want to change the document title html from the link is loaded in a div. When you're loading a file in a div via jQuery .load
you're just inserting the complete response text after an ajax request in it. So with all the stuff which shouldn't be in a div like the title
or meta
tag. However the title of the current document (http://bramvanroy.be/sectionLoaderTest/index.html
) is defined in the title
which is inside the head
tag and not in the title
tag inside a div so that's why the document title doesn't change.
So how can I fix it?
Good question, because the title
element inside a div
element is invalid, most browsers will remove it so you can't just use this:
document.title = $("#sectionContainer title").text();
because the title
element may not exist.
So what we need is the direct response from the jQuery .load
function. I can get it by adding the callback argument to the function:
$("#sectionContainer")
.hide()
.load(newLoadedHtml, function(responseText) {
document.title = $(responseText).filter("title").text();
})
.fadeIn("fast");
What you may not understand is why I use the .filter
and not the .find
function. This is because jQuery is kind of parsing html
, head
and body
tags out of the html but not removing there child elements.
Answer 2 - Optimize the load time of the mainpage
A document is getting loaded from to top to the bottom.
So first of all the css, JavaScript etc. should be loaded and then the the main document.
Because jQuery is always waiting for the document before it's executing it wouldn't be a very bad idea to put all your script
elements right before the end of the body, so that your HTML can be loaded before.
BtW I just had this problem at the first time after that everything was cached and the document was loading very fast.
Answer 3 - Fix the active-class when going forward and backward
I would say loop trough the href
attributes of the a
elements and compare it with the data from History.getState()
. Should be easy.
You did some mistakes in your code - Your fixed code:
You appended the hash #content
to all URLs.. it doesn't make sense and it will be removed by jQuery again: https://github.com/jquery/jquery/blob/master/src/ajax.js#L617 (Comes from lines: 158, 190, 337, 617 - rhash is on line 6)
$(document).ready(function () {
var firstLink = $("ul > li:first-child > a");
var menuLink = $("ul > li > a");
var firstLoadedHtml = firstLink.attr("href");
$("#sectionContainer").hide().load(firstLoadedHtml).fadeIn("fast");
firstLink.addClass("active");
menuLink.click(function(e) {
e.preventDefault();
e.stopImmediatePropagation();
var newLoadedHtml = $(this).attr("href");
History.pushState(null, newLoadedHtml, newLoadedHtml);
$("#sectionContainer")
.hide()
.load(newLoadedHtml, function(responseText) {
document.title = $(responseText).filter("title").text();
})
.fadeIn("fast");
});
History.Adapter.bind(window, "statechange", function() {
menuLink.removeClass("active");
$("a[href='" + History.getState().title + "']").addClass("active");
$('#sectionContainer').load(document.location.href, function(responseText) {
document.title = $(responseText).filter("title").text();
});
});
});
这篇关于pushState()和popState():操纵浏览器的历史的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!