使用Sammy.js取消路由而不影响历史记录

9
我想用Sammy拦截所有路由更改,首先检查是否存在待处理的操作。我使用sammy.before API来实现这一点,并返回false以取消路由。这将使用户停留在“页面”上,但仍会更改浏览器地址栏中的哈希值并将路由添加到浏览器历史记录中。如果我取消路由,则不希望它出现在地址栏或历史记录中,而是希望地址保持不变。
目前,为了解决这个问题,我可以调用window.history.back(yuk)返回到历史记录中的原始位置,或者使用sammy.redirect。但这两种方法都不太理想。
有没有办法使Sammy真正取消路由,使其停留在当前路由/页面,保持地址栏不变,并且不添加到历史记录中?
如果没有,是否有其他路由库可以做到这一点?
sammy.before(/.*/, function () {
    // Can cancel the route if this returns false
    var response = routeMediator.canLeave();

if (!isRedirecting && !response.val) {
    isRedirecting = true;
    // Keep hash url the same in address bar
    window.history.back();
    //this.redirect('#/SpecificPreviousPage'); 
}
else {
    isRedirecting = false;
}
return response.val;
});
4个回答

17

如果有人遇到同样的问题,这里是我的解决方案。我决定使用sammy的context.setLocation功能来处理路由重置。

sammy.before(/.*/, function () {
    // Can cancel the route if this returns false
    var
        context = this,
        response = routeMediator.canLeave();

    if (!isRedirecting && !response.val) {
        isRedirecting = true;
        toastr.warning(response.message); // toastr displays the message
        // Keep hash url the same in address bar
        context.app.setLocation(currentHash);
    }
    else {
        isRedirecting = false;
        currentHash = context.app.getLocation();
    }
    return response.val;
});

哈哈哈,John,我是通过搜索有关你在SPA系列中如何实现这一点的更多信息来到这里的 :-) - Luc Morin

1

当使用问题和答案中提供的代码时,您必须注意取消的路由也将被阻止所有未来的调用,routeMediator.canLeave不会再次评估。使用此方法无法根据当前状态两次调用并取消路由。


1
嗯,我很好奇你为什么这么说。我已经使用了这段代码,它并没有阻止未来对canLeave的调用。你能详细说明一下吗?如果我有一个错误,我想要知道如何修复它。 - John Papa
Sammy的before文档中指出:“如果任何回调函数明确返回false,则进一步回调和路由本身的执行将停止。” - 这就是我在上面的代码中观察到的。这仅在连续两次访问被阻止的路由时发生。在访问其他路由之间,一切都正常。 - Björn Peter
2
路由被暂停了,是的。但它并没有说未来对路由的调用会被阻止。我没有看到这种行为,我可以让它停止离开,下一次还是会调用它。 - John Papa

0

当我在SPA/Knockout课程中使用SammyJS时,我能够产生与John Papa相同的结果。

我使用Crossroads JS作为路由器,它依赖于Hasher JS来监听浏览器“发出”的URL变化。

代码示例如下:

hasher.changed.add(function(hash, oldHash) {
    if (pageViewModel.isDirty()){
        console.log('trying to leave from ' + oldHash + ' to ' + hash);

        hasher.changed.active = false;
        hasher.setHash(oldHash);
        hasher.changed.active = true;

        alert('cannot leave. dirty.');
    }
    else {
        crossroads.parse(hash);
        console.log('hash changed from ' + oldHash + ' to ' + hash);
        }
});

0

在重新审视旧项目并遇到类似情况后,我想分享另一种方法,以防其他人被引导到这里。

所需的基本上是一个现代的“身份验证守卫”模式,用于拦截页面并根据凭据进行重定向。

使用如下定义的Sammy.around(callback)非常有效: Sammy.js文档:Sammy.Application around(callback)

然后,只需执行以下操作...

(function ($) {
    var app = Sammy("body");

    app.around(checkLoggedIn);

    function canAccess(hash) {
        /* access logic goes here */
        return true;
    }

    // Authentication Guard
    function authGuard(callback) {
        var context = this;
        var currentHash = app.getLocation();
        if (!canAccess(currentHash)) {
            // redirect
            context.redirect("#/login");
        }
        else {
            // execute the route path
            callback();
        }
    };

})(jQuery);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接