在 FF 中的 iframe 中使用 "replaceWith" 运行 在 Ember 应用程序中使用 "history.back" 的奇怪行为
Odd behavior with "history.back" in Ember app using "replaceWith" running in iframe in FF
更新:这不是 Ember 中的错误,而是 Firefox 中的错误。参见 https://bugzilla.mozilla.org/show_bug.cgi?id=301307。一旦赏金到期,我将删除这个问题(除非有人提出解决方法)。
我在 iframe 中有一个 Ember 应用 运行。页面A有一个link到页面B,页面B有一个link到页面C使用'Route#replaceWith'实现,这样B就不会留在历史堆栈中。页面 C 有一个 link 调用 history.back()
,它应该 return 到页面 A。它对页面 A 执行 return,但在 Firefox 中 仅在重新加载后页面。没有理由重新加载页面,并且在 Chrome 中未观察到此行为。此行为也不会发生,除非应用程序在 iframe 中 运行。
这是应用程序:
// router.js
var Router = Ember.Router.extend({location:'hash'});
Router.map(function() { 'abc'.split('').forEach(x => this.route(x));});
export default Router;
// a/route.js
export default Ember.Route.extend({actions:{b:function(){this.transitionTo('b');}}});
// a/template.js
This is A.
<a href="#" {{action 'b'}}>Goto B!</a>
// b/route.js
import Ember from 'ember';
export default Ember.Route.extend({ actions: { link: function() { this.replaceWith('c'); } } });
// b/template.js
This is B.
<a href="#" {{action 'link'}}>GOTO C (no history entry)</a>
// c/route.js
export default Ember.Route.extend({ actions: { back: function() { history.back(); } } });
// c/template.hbs
This is C
<a href="#" {{action 'back'}}>Go back</a>
如果我将 B 中的 replaceWith
更改为 transitionTo
,并将 C 中的 history.back()
更改为 history.go(-2)
,则一切正常,不会发生重新加载。但这不是一个可行的解决方案,因为浏览器后退按钮还必须将用户从 C 返回到 A。
我正在使用 locationType: 'hash'
,无法轻易更改。 locationType: 'history'
.
不会出现此问题
我能想到为什么 Firefox 在尝试 return 到 A 时可能会重新加载页面的唯一原因是由于更积极的缓存管理。如果这确实是问题所在,那么我想知道是否有某种方法可以告诉 Firefox 放松并从缓存中将页面返回到历史记录中,而不是再次返回到服务器。
仅供参考,这是一个新鲜的小 Ember 应用程序 运行 堆栈中所有内容的最新版本。
感谢所有想法。
保持散列位置类型并解决 Firefox 错误的一种方法是通过扩展内置 Ember HashLocation 并重写 replaceURL 函数以使用 history.replaceState 而不是 location.replace.
HashWithFFWorkaroundLocation = Ember.HashLocation.extend({
implementation: 'hash-with-ff-workaround',
replaceURL(path) {
var history = this.get('history') || window.history;
var useFixOnlyForFF = true; // Use the fix only in Firefox?
var isFF = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
var useFix = useFixOnlyForFF && isFF || !useFixOnlyForFF;
if (useFix && 'object' === typeof history && 'function' === typeof history.replaceState)
{
var state = { path: path };
history.replaceState(state, null, '#' + path);
}
else
{
// Next line is the original implementation which triggers a bug in Firefox
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=301307
this.get('location').replace('#' + path);
}
this.set('lastSetUrl', path);
}
});
然后您将自定义实现注册为具有初始值设定项的新位置类型
Ember.Application.initializer({
name: 'hash-with-ff-workaround-location',
initialize: function(container, application) {
// register the custom implementation for locationType: hash-with-ff-workaround
application.register('location:hash-with-ff-workaround', HashWithFFWorkaroundLocation);
}
});
将上述代码添加到项目后,您需要在现有代码中更改的唯一行是
// router.js
var Router = Ember.Router.extend({ location: 'hash-with-ff-workaround' });
你可以正常调用this.replaceWith('c');
.
这是 jsFiddle 演示:http://jsfiddle.net/Ma3x/hs39vbqg/6/
在 jsFiddle 中,我启用了对所有路由步骤的详细记录。如果您检查控制台输出,您可以看到在使用 Back/Forward 按钮或 history.back/forward.[=15 时,转换正常地从 c 返回到 a 并向前返回到 c 跳过 b 正如预期的那样=]
更新:这不是 Ember 中的错误,而是 Firefox 中的错误。参见 https://bugzilla.mozilla.org/show_bug.cgi?id=301307。一旦赏金到期,我将删除这个问题(除非有人提出解决方法)。
我在 iframe 中有一个 Ember 应用 运行。页面A有一个link到页面B,页面B有一个link到页面C使用'Route#replaceWith'实现,这样B就不会留在历史堆栈中。页面 C 有一个 link 调用 history.back()
,它应该 return 到页面 A。它对页面 A 执行 return,但在 Firefox 中 仅在重新加载后页面。没有理由重新加载页面,并且在 Chrome 中未观察到此行为。此行为也不会发生,除非应用程序在 iframe 中 运行。
这是应用程序:
// router.js
var Router = Ember.Router.extend({location:'hash'});
Router.map(function() { 'abc'.split('').forEach(x => this.route(x));});
export default Router;
// a/route.js
export default Ember.Route.extend({actions:{b:function(){this.transitionTo('b');}}});
// a/template.js
This is A.
<a href="#" {{action 'b'}}>Goto B!</a>
// b/route.js
import Ember from 'ember';
export default Ember.Route.extend({ actions: { link: function() { this.replaceWith('c'); } } });
// b/template.js
This is B.
<a href="#" {{action 'link'}}>GOTO C (no history entry)</a>
// c/route.js
export default Ember.Route.extend({ actions: { back: function() { history.back(); } } });
// c/template.hbs
This is C
<a href="#" {{action 'back'}}>Go back</a>
如果我将 B 中的 replaceWith
更改为 transitionTo
,并将 C 中的 history.back()
更改为 history.go(-2)
,则一切正常,不会发生重新加载。但这不是一个可行的解决方案,因为浏览器后退按钮还必须将用户从 C 返回到 A。
我正在使用 locationType: 'hash'
,无法轻易更改。 locationType: 'history'
.
我能想到为什么 Firefox 在尝试 return 到 A 时可能会重新加载页面的唯一原因是由于更积极的缓存管理。如果这确实是问题所在,那么我想知道是否有某种方法可以告诉 Firefox 放松并从缓存中将页面返回到历史记录中,而不是再次返回到服务器。
仅供参考,这是一个新鲜的小 Ember 应用程序 运行 堆栈中所有内容的最新版本。
感谢所有想法。
保持散列位置类型并解决 Firefox 错误的一种方法是通过扩展内置 Ember HashLocation 并重写 replaceURL 函数以使用 history.replaceState 而不是 location.replace.
HashWithFFWorkaroundLocation = Ember.HashLocation.extend({
implementation: 'hash-with-ff-workaround',
replaceURL(path) {
var history = this.get('history') || window.history;
var useFixOnlyForFF = true; // Use the fix only in Firefox?
var isFF = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
var useFix = useFixOnlyForFF && isFF || !useFixOnlyForFF;
if (useFix && 'object' === typeof history && 'function' === typeof history.replaceState)
{
var state = { path: path };
history.replaceState(state, null, '#' + path);
}
else
{
// Next line is the original implementation which triggers a bug in Firefox
// See: https://bugzilla.mozilla.org/show_bug.cgi?id=301307
this.get('location').replace('#' + path);
}
this.set('lastSetUrl', path);
}
});
然后您将自定义实现注册为具有初始值设定项的新位置类型
Ember.Application.initializer({
name: 'hash-with-ff-workaround-location',
initialize: function(container, application) {
// register the custom implementation for locationType: hash-with-ff-workaround
application.register('location:hash-with-ff-workaround', HashWithFFWorkaroundLocation);
}
});
将上述代码添加到项目后,您需要在现有代码中更改的唯一行是
// router.js
var Router = Ember.Router.extend({ location: 'hash-with-ff-workaround' });
你可以正常调用this.replaceWith('c');
.
这是 jsFiddle 演示:http://jsfiddle.net/Ma3x/hs39vbqg/6/
在 jsFiddle 中,我启用了对所有路由步骤的详细记录。如果您检查控制台输出,您可以看到在使用 Back/Forward 按钮或 history.back/forward.[=15 时,转换正常地从 c 返回到 a 并向前返回到 c 跳过 b 正如预期的那样=]