使用hashbang防止用户在单页应用中离开路由
Prevent user to leave the route in a single page app with hashbang
我正在使用Sammy.js为我的单页应用程序。我想创建类似于SO的功能(当你输入你的问题并尝试离开页面时,它会问你是否确定)。
如果它不是一个单页应用程序,我会这样做:
$(window).bind('beforeunload', function(){
return 'Are you sure you want to leave?';
});
问题在于,在单页应用程序中,用户实际上并没有离开页面,而是改变了他的document.location.hash
(他可以通过关闭页面来离开页面)。有没有办法为SPA制作类似的东西,最好是用sammy.js?
我们在工作中的单页web应用程序中也遇到了类似的问题。我们有一些页面可能是脏的,如果它们是脏的,我们想要阻止导航离开该页面,直到用户验证可以这样做。因为我们想要阻止导航,所以我们不能监听onhashchange事件,该事件是在哈希值更改之后触发的,而不是在此之前。因此,我们决定覆盖默认的LocationProxy,以包含允许我们在位置更改之前有选择地阻止导航的逻辑。
考虑到这一点,下面是我们使用的代理:PreventableLocationProxy = (function () {
function PreventableLocationProxy(delegateProxy, navigationValidators) {
/// <summary>This is an implementation of a Sammy Location Proxy that allows cancelling of setting a location based on the validators passed in.</summary>
/// <param name="delegateProxy" type="Sammy.DefaultLocationProxy">The Location Proxy which we will delegate all method calls to.</param>
/// <param name="navigationValidators" type="Function" parameterArray="true" mayBeNull="true">One or more validator functions that will be called whenever someone tries to change the location.</param>
this.delegateProxy = delegateProxy;
this.navigationValidators = Array.prototype.slice.call(arguments, 1);
}
PreventableLocationProxy.prototype.bind = function () {
this.delegateProxy.bind();
};
PreventableLocationProxy.prototype.unbind = function () {
this.delegateProxy.unbind();
};
PreventableLocationProxy.prototype.getLocation = function () {
return this.delegateProxy.getLocation();
};
PreventableLocationProxy.prototype.setLocation = function (new_location) {
var doNavigation = true;
_.each(this.navigationValidators, function (navValidator) {
if (_.isFunction(navValidator)) {
// I don't just want to plug the result of the validator in, it could be anything!
var okayToNavigate = navValidator(new_location);
// A validator explicitly returning false should cancel the setLocation call. All other values will
// allow navigation still.
if (okayToNavigate === false) {
doNavigation = false;
}
}
});
if (doNavigation) {
return this.delegateProxy.setLocation(new_location);
}
};
return PreventableLocationProxy;
}());
这段代码本身非常简单,它是一个javascript对象,它接受一个委托代理,以及一个或多个验证器函数。如果其中任何一个验证器显式地返回false,那么导航将被阻止,位置也不会改变。否则,允许导航。为了做到这一点,我们必须重写锚标记的默认onclick处理,通过Sammy.Application.setLocation路由它。然而,一旦完成,这就允许我们的应用程序处理脏页面逻辑。
为了更好地测量,下面是我们的脏页面验证器:
function preventNavigationIfDirty(new_location) {
/// <summary>This is an implementation of a Sammy Location Proxy that allows cancelling of setting a location based on the validators passed in.</summary>
/// <param name="new_location" type="String">The location that will be navigated to.</param>
var currentPageModels = [];
var dirtyPageModels = [];
//-----
// Get the IDs of the current virtual page(s), if any exist.
currentPageModels = _.keys(our.namespace.currentPageModels);
// Iterate through all models on the current page, looking for any that are dirty and haven't had their changes abored.
_.forEach(currentPageModels, function (currentPage) {
if (currentPage.isDirty() && currentPage.cancelled === false) {
dirtyPageModels.push(currentPage);
}
});
// I only want to show a confirmation dialog if we actually have dirty pages that haven't been cancelled.
if (dirtyPageModels.length > 0) {
// Show a dialog with the buttons okay and cancel, and listen for the okay button's onclick event.
our.namespace.confirmDirtyNavigation(true, function () {
// If the user has said they want to navigate away, then mark all dirty pages with the cancelled
// property then do the navigating again. No pages will then prevent the navigation, unlike this
// first run.
_.each(dirtyPageModels, function (dirtyPage) {
dirtyPage.cancelled = true;
});
our.namespace.sammy.setLocation(new_location);
});
// Returns false in order to explicitly cancel the navigation. We don't need to return anything in any
// other case.
return false;
}
}
请记住,如果用户显式地更改位置,此解决方案将不起作用,但这不是我们想要支持的用例。希望这能让你更接近自己的解决方案
相关文章:
- 如何将HTML id分配给元素,以及如何将JavaScript应用于元素
- Canvas Html5绘图应用程序,移动画布会导致重大问题
- Emberjs应用程序加载在除Index之外的所有路由上
- 使用电话间隙在Android应用程序中显示SQL Lite的数据
- 跟踪在页面加载时应用内联样式的JavaScript
- 在AngularJS应用程序中使用封装指令和路由的推荐方式是什么
- 如果文本字段为空,则使用JavaScript应用CSS样式
- Windows8应用程序(html&Javascript):从图片库(除了文件选择器)显示图像的另一种方式
- 为什么在单独的函数中应用时转换会闪烁/断断续续(D3)
- angular 1.5应用程序中的导航栏
- 在Web应用程序中使用Highcharts javascript
- angularjs+rails应用程序中未显示模板
- 从html创建一个指令,该指令按类名应用函数
- 使用acess代币登录Facebook,并通过网络应用程序离线发布
- 当主导航离开视图时,为粘性导航应用样式
- Angular 2:当我离开路由时,如何应用回调
- 聊天应用程序 - 当有人进入/离开房间时,用声音通知用户
- 在离开页面后重置我的应用程序的redux状态
- 使用hashbang防止用户在单页应用中离开路由
- 如何从上次离开的地方继续运行Rails应用程序