简体   繁体   English

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

[英]Cancel route using Sammy.js without affecting history

I want to intercept all route changes with Sammy to first check if there is a pending action. 我想拦截Sammy的所有路线变化,首先检查是否有待处理的动作。 I have done this using the sammy.before API and I return false to cancel the route. 我使用sammy.before API完成了这个,我返回false来取消路由。 This keeps the user on the 'page' but it still changes the hash in the browsers address bar and adds the route to the browsers' history. 这使用户保持在“页面”上,但它仍然会更改浏览器地址栏中的哈希值,并将路径添加到浏览器的历史记录中。 If I cancel the route, I dont want it in the address bar nor history, but instead I expect the address to stay the same. 如果我取消路线,我不想在地址栏或历史记录中,但我希望地址保持不变。

Currently, to get around this I can either call window.history.back (yuk) to go back to the original spot in the history or sammy.redirect. 目前,要解决此问题,我可以调用window.history.back(yuk)返回历史记录中的原始位置或sammy.redirect。 Both of which are less than ideal. 两者都不太理想。

Is there a way to make sammy truly cancel the route so it stays on the current route/page, leaves the address bar as is, and does not add to the history? 有没有办法让sammy真正取消路由,使其保持在当前路由/页面上,保留地址栏,并且不添加到历史记录中?

If not, is there another routing library that will do this? 如果没有,是否有另一个路由库将执行此操作?

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;
});

In case someone else hits this, here is where I ended up. 如果其他人遇到这个,这里是我结束的地方。 I decided to use the context.setLocation feature of sammy to handle resetting the route. 我决定使用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;
});

When using the code provided within the question and answer you have to notice that the route you cancelled will also be blocked for all future calls, routeMediator.canLeave will not be evaluated again. 使用问题和答案中提供的代码时,您必须注意到您取消的路线也将在以后的所有呼叫中被阻止,因此不会再次评估routeMediator.canLeave。 Calling a route twice and cancelling it depending on current state is not possible with this. 两次调用路由并根据当前状态取消它是不可能的。

I could produce the same results as John Papa did when he used SammyJS on the SPA/Knockout course. 我可以产生与John Papa在SPA / Knockout课程中使用SammyJS时所做的相同的结果。

I used Crossroads JS as the router, which relies on Hasher JS to listen to URL changes "emitted" by the browser. 我使用Crossroads JS作为路由器,它依赖于Hasher JS来监听浏览器“发出”的URL更改。

Code sample is: 代码示例是:

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);
        }
});

After revisiting an older project and having a similar situation, I wanted to share another approach, just in case someone else is directed here. 在重新审视一个较旧的项目并遇到类似情况后,我想分享另一种方法,以防其他人被引导到这里。

What was needed was essentially a modern "auth guard" pattern for intercepting pages and redirecting based on credentials. 所需要的基本上是用于截取页面和基于凭证重定向的现代“auth guard”模式。

What worked well was using Sammy.around(callback) as defined here: Sammy.js docs: Sammy.Application around(callback) 运行良好的是使用Sammy.around(callback)如下所示: Sammy.js docs:Sammy.Application around(callback)

Then, simply do the following... 然后,只需执行以下操作......

(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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM