如何在 JavaScript 中使用 window.history?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31528432/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I use window.history in JavaScript?
提问by Yay295
I found a lot of questions about this on Stack Overflow, but they were all very specific about certain parts. I did find thisquestion whose answers provide some nice references, but they don't actually explain how it all works, and their examples hardly do anything. I want to know more about how it all works together, and I want to use vanilla JavaScript.
我在 Stack Overflow 上发现了很多关于此的问题,但它们都针对某些部分非常具体。我确实发现这个问题的答案提供了一些很好的参考,但他们实际上并没有解释这一切是如何运作的,而且他们的例子几乎没有任何作用。我想更多地了解它们是如何协同工作的,并且我想使用 vanilla JavaScript。
(Also, many of the answers on other questions are years old.)
(此外,关于其他问题的许多答案已有多年历史。)
回答by Yay295
GETTING STARTED
入门
First of all, you can remove the window
part. Just history
works fine. But before we get into how everything works together, we need to know what we can use.
首先,您可以删除该window
部分。只是history
工作正常。但在我们了解一切如何协同工作之前,我们需要知道我们可以使用什么。
Important Events
重要的事件
window.onload
窗口加载
This event fires whenever your webpage is loaded. There are two cases that will fire this event:
每当您的网页加载时,就会触发此事件。有两种情况会触发此事件:
- When your webpage is navigated to from another webpage. Note that I wrote webpage, not website. Moving between pages on the same site will trigger this event.
- Just after your webpage is refreshed.
- 当您的网页从另一个网页导航到时。请注意,我写的网页页面,而不是web站点。在同一站点上的页面之间移动将触发此事件。
- 就在您的网页刷新后。
window.onpopstate
window.onpopstate
This event fires when you navigate between history states that youhave set. Your browser automatically sets history states (to null) during normal browsing, but navigating to/from these states will not trigger this event.
当你的历史状态之间导航此事件是您已设置。您的浏览器在正常浏览期间会自动设置历史状态(为空),但在这些状态之间导航不会触发此事件。
window.onunload
窗口.onunload
This event fires whenever your webpage is unloaded. There are two cases that will fire this event:
只要您的网页被卸载,就会触发此事件。有两种情况会触发此事件:
- When you navigate to another webpage from your webpage.
- Just before your webpage is refreshed.
- 当您从您的网页导航到另一个网页时。
- 就在您的网页刷新之前。
Important Objects
重要对象
The history interface contains five functions (described below), two read-only objects (described here), and works a bit like a linked list. The two objects contained in each 'link' of the history object are:
历史接口包含五个函数(如下所述)、两个只读对象(此处描述),其工作方式有点像链表。历史对象的每个“链接”中包含的两个对象是:
- length - This is the number of history states for the current browser window. It starts at 1.
- state - This is a JavaScript object that can contain practically anything. It is
null
by default.
- 长度 - 这是当前浏览器窗口的历史状态数。它从 1 开始。
- state - 这是一个 JavaScript 对象,几乎可以包含任何内容。它是
null
默认的。
You can access them by calling history.length
and history.state
respectively, though history.state
can only be used to get the currenthistory state.
您可以通过分别调用history.length
和来访问它们history.state
,但history.state
只能用于获取当前的历史状态。
Important Functions
重要功能
history.go(distance)
history.go(距离)
This function does the same thing as pressing the back or forward button in your browser, with the added functionality of being able to specify exactly how far you want to go. For example, history.go(3)
has the same effect as would pushing your forward button three times, without actually loading the pages between your start and end locations. A negative value will likewise move you backwards through your history. history.go(0)
, history.go()
, and even history.go(NaN)
have the same effect as refreshing the page (this does not trigger the popstate
event). If you cannot move forward/backward as far as specified, the function will do nothing.
此功能与按浏览器中的后退或前进按钮执行相同的操作,并增加了能够准确指定您想要走多远的功能。例如,history.go(3)
与按三下前进按钮的效果相同,而无需实际加载开始和结束位置之间的页面。负值同样会使您在历史记录中倒退。history.go(0)
, history.go()
, 甚至history.go(NaN)
和刷新页面有同样的效果(这个不会触发popstate
事件)。如果您不能按照指定的方式向前/向后移动,则该功能将不执行任何操作。
history.back()
历史.back()
This function has the same functionality as the back button in your browser. It is equivalent to history.go(-1)
. If it cannot go back, the function will do nothing.
此功能与浏览器中的后退按钮具有相同的功能。它相当于history.go(-1)
。如果无法返回,则该函数将不执行任何操作。
history.forward()
历史.forward()
This function has the same functionality as the forward button in your browser. It is equivalent to history.go(1)
. If it cannot go forward, the function will do nothing.
此功能与浏览器中的前进按钮具有相同的功能。它相当于history.go(1)
。如果它不能前进,该函数将什么也不做。
history.replaceState(state, title[, location])
history.replaceState(state, title[, location])
This function replaces the current history state. It takes three arguments, though the last one is optional. The arguments are:
此函数替换当前历史状态。它需要三个参数,尽管最后一个是可选的。论据是:
- state - This is the most important argument. The object you give to this argument will be saved to
history.state
for later retrieval. This is a deep copy, so if you later modify the original object it will not change the saved state. You could also set this tonull
, but if you aren't going to use it, there's not much point in usinghistory
at all. - title - The HTML Standard suggests that a string passed to this argument could be used by the browser in the user interface, but no browser currently does anything with it.
- location - This argument allows you to change the URL relative to the current page. It cannot be used to change the URL to that of another website, but it can be used to change the URL to that of another page on yourwebsite. I would advise against this however, as the page is not actually reloaded even though the URL is of another page. Using back/forward will show the changed URL, but will not change the page, and will trigger
popstate
rather thanload
orunload
. Refreshing the page after changing its URL will load the page specified by the URL rather than the page you were previously on. This functionality could be used to provide a link to your page in its current state, but I would recommend only changing the query string rather than the full URL. If this argument is not used, the URL will not change.
- state - 这是最重要的参数。您提供给此参数的对象将被保存以
history.state
供以后检索。这是一个深拷贝,所以如果你以后修改原始对象,它不会改变保存的状态。您也可以将其设置为null
,但如果您不打算使用它,则根本没有使用history
的意义。 - title - HTML 标准建议浏览器可以在用户界面中使用传递给此参数的字符串,但目前没有浏览器对其进行任何操作。
- location - 此参数允许您更改相对于当前页面的 URL。它不能用于将 URL 更改为另一个网站的 URL,但可以用于将 URL 更改为您网站上另一个页面的 URL 。但是,我建议不要这样做,因为即使 URL 是另一个页面,该页面实际上也不会重新加载。使用后退/前进将显示更改后的 URL,但不会更改页面,并且会触发
popstate
而不是load
或unload
. 更改 URL 后刷新页面将加载 URL 指定的页面,而不是您之前所在的页面。此功能可用于提供指向当前状态的页面的链接,但我建议仅更改查询字符串而不是完整的 URL。如果不使用此参数,则 URL 不会更改。
history.pushState(state, title[, location])
history.pushState(状态,标题[,位置])
This function works the same as history.replaceState
, except it puts the new state afterthe current state instead of replacing the current state. All history states that could have previously been accessed with forward
are discarded, and the new state becomes the current state.
该功能的工作方式相同history.replaceState
,但它提出的新的状态后,目前的状态,而不是替换当前状态。之前可以访问的所有历史状态forward
都被丢弃,新状态成为当前状态。
ASSEMBLING THE PIECES
组装零件
The history interface is very useful for allowing your users to navigate through dynamically generated content from within their browser without having to reload the entire page, but you need to be mindful of all the possible things your users could do that could affect the history state.
历史记录界面对于允许您的用户从浏览器中浏览动态生成的内容非常有用,而无需重新加载整个页面,但您需要注意用户可能执行的所有可能影响历史记录状态的事情。
- First time navigating to your page
- Should your users be greeted with a menu/list, some specific dynamically generated content, or maybe some random dynamically generated content?
- Will your page display correctly without
history
, or even JavaScript?
- Using
back/forward
to return to your page- Should your users see the same thing they saw their first time, or should they see the result of their visit reflected in the content? (A "Welcome Back" message might be a nice touch to some, but an unwanted distraction to others.)
- Refreshing your page
- Should you get a new page, return to the start page, or reload the same page? (Your users probably won't expect that last one if the URL hasn't changed.)
- Using
back/forward
from a refreshed page- Should you get new content relative to the refreshed page, or reload the previously saved state?
- Navigating away from your page
- Do you need to save anything before leaving?
- Returning to your page via a deep link
- Do you have code in place to recognize and handle a deep link?
- 第一次导航到您的页面
- 您的用户是否应该看到一个菜单/列表、一些特定的动态生成的内容,或者一些随机的动态生成的内容?
- 您的页面在没有
history
,甚至没有 JavaScript 的情况下能正确显示吗?
- 使用
back/forward
返回到您的网页- 您的用户应该看到他们第一次看到的东西,还是应该看到他们访问的结果反映在内容中?(“欢迎回来”的信息对某些人来说可能是一种很好的感觉,但对其他人来说却是一种不必要的分心。)
- 刷新页面
- 您应该获得一个新页面,返回到起始页面,还是重新加载同一页面?(如果 URL 没有改变,您的用户可能不会期待最后一个。)
- 使用
back/forward
从刷新页面- 您应该获取与刷新页面相关的新内容,还是重新加载之前保存的状态?
- 离开您的页面
- 离开前需要保存任何东西吗?
- 通过深层链接返回到您的页面
- 您是否有代码来识别和处理深层链接?
Note there is no way to delete a saved state (other than a specific case with pushState()
mentioned above). You can only replace it with new content.
请注意,无法删除已保存的状态(pushState()
上述特定情况除外)。您只能用新内容替换它。
PUTTING IT ALL TOGETHER
把一切放在一起
Since this is starting to get a bit wordy, lets finish it off with some code.
由于这开始变得有点冗长,让我们用一些代码来结束它。
// This function is called when the page is first loaded, when the page is refreshed,
// and when returning to the page from another page using back/forward.
// Navigating to a different page with history.pushState and then going back
// will not trigger this event as the page is not actually reloaded.
window.onload = function() {
// You can distinguish a page load from a reload by checking performance.navigation.type.
if (window.performance && window.PerformanceNavigation) {
let type = performance.navigation.type;
if (type == PerformanceNavigation.TYPE_NAVIGATE) {
// The page was loaded.
} else if (type == PerformanceNavigation.TYPE_RELOAD) {
// The page was reloaded.
} else if (type == PerformanceNavigation.TYPE_BACK_FORWARD) {
// The page was navigated to by going back or forward,
// though *not* from a history state you have set.
}
}
// Remember that the browser automatically sets the state to null on the
// first visit, so if you check for this and find it to be null, you know
// that the user hasn't been here yet.
if (history.state == null) {
// Do stuff on first load.
} else {
// Do stuff on refresh or on returning to this page from another page
// using back/forward. You may want to make the window.onpopstate function
// below a named function, and just call that function here.
}
// You can of course have code execute in all three cases. It would go here.
// You may also wish to set the history state at this time. This could go in the
// if..else statement above if you only want to replace the state in certain
// circumstances. One reason for setting the state right away would be if the user
// navigates to your page via a deep link.
let state = ...; // There might not be much to set at this point since the page was
// just loaded, but if your page gets random content, or time-
// dependent content, you may want to save something here so it can
// be retrieved again later.
let title = ...; // Since this isn't actually used by your browser yet, you can put
// anything you want here, though I would recommend setting it to
// null or to document.title for when browsers start actually doing
// something with it.
let URL = ...; // You probably don't want to change the URL just yet since the page
// has only just been loaded, in which case you shouldn't use this
// variable. One reason you might want to change the URL is if the
// user navigated to this page with a query string in the URL. After
// reading the query string, you can remove it by setting this
// variable to: location.origin + location.pathname
history.replaceState(state, title, URL); // Since the page has just been loaded, you
// don't want to push a new state; you should
// just replace the current state.
}
// This function is called when navigating between states that you have set.
// Since the purpose of `history` is to allow dynamic content changes without
// reloading the page (ie contacting the server), the code in this function
// should be fairly simple. Just things like replacing text content and images.
window.onpopstate = function() {
// Do things with history.state here.
}
// This function is called right before the page is refreshed, and right
// before leaving the page (not counting history.replaceState). This is
// your last chance to set the page's history state before leaving.
window.onunload = function() {
// Finalize the history state here.
}
Notice that I never called history.pushState
anywhere. This is because history.pushState
should not be called anywhere in these functions. It should be called by the function that actually changes the page in some way that you want your users to be able to use the back button to undo.
请注意,我从未history.pushState
在任何地方打电话。这是因为history.pushState
不应在这些函数中的任何地方调用。它应该由以某种方式实际更改页面的函数调用,您希望您的用户能够使用后退按钮撤消。
So in conclusion, a generic setup might work like this:
所以总而言之,通用设置可能像这样工作:
- Check
if (history.state == null)
in thewindow.onload
function.- If true, overwrite the history state with new information.
- If false, use the history state to restore the page.
- While the user is navigating the page, call
history.pushState
when important things happen that should be undoable with the back button. - If/When the user uses their back button and the
popstate
event is triggered, use the history state you set to return the page to its previous state.- Do likewise if/when the user then uses their forward button.
- Use the
unload
event to finalize the history state before the user leaves the page.
- 签
if (history.state == null)
入window.onload
函数。- 如果为真,则用新信息覆盖历史状态。
- 如果为 false,则使用历史记录状态来恢复页面。
- 当用户浏览页面时,
history.pushState
当发生重要的事情时调用,这些事情应该可以用后退按钮撤消。 - 如果/当用户使用他们的后退按钮并且
popstate
事件被触发时,使用您设置的历史状态将页面返回到其先前状态。- 如果/当用户然后使用他们的前进按钮时也这样做。
- 使用该
unload
事件在用户离开页面之前完成历史状态。