考虑以下:
var originalPath = window.location.pathname.toString();
history.pushState({ value: 'Foo' }, '', 'state-1');
history.pushState({ value: 'Bar' }, '', 'state-2');
history.pushState({ value: 'Baz' }, '', 'state-3');
history.back();
history.back();
console.log(history.state.value);
//So we can hit refresh and see the results again...
setTimeout(function () {
history.replaceState(null, '', originalPath);
}, 250);
人们会期望这段代码返回“Foo”——在 Firefox 和我的 IE 鸭拳中,这正是它所做的——但在 Chrome 中,它以“Baz”响应。
经过一番调查,我解决了问题:IE和Firefox同步更新历史记录,如果需要加载任何页面,则异步进行。Chrome 似乎立即进入异步状态。
证据:
window.onpopstate = function () {
console.log('ping');
}
history.pushState({ value: 'Foo' }, '', 'state-1');
history.back();
console.log('pong');
在 Firefox 中,这会返回 'ping';'pong' - 表示事件是作为 history.back() 调用的一部分分派的。在 Chrome 中,这会返回 'pong';'ping' - 表示事件被放置在队列中等待调度。
如果这个事件分派模型没有被用来管理历史和位置对象的状态,这不会那么糟糕 - 但显然它是。
window.onpopstate = function () {
console.log('Event...', history.state, window.location.pathname.toString());
}
history.pushState({ value: 'Foo' }, '', 'state-1');
history.back();
console.log('Inline...', history.state, window.location.pathname.toString());
这是一个有趣的怪癖,需要使用 jQuery Deferred 链才能正常工作以进行我的单元测试。我对此并不特别高兴,但你能做什么?