防止用户离开而未保存更改

5
我目前正在使用Backbone.Marionette创建单页应用程序,在其中一个视图中,用户可以使用未保存的更改导航离开。我可以控制一些事件,比如视图内的按钮和菜单选项,会带走用户,但有些其他事件需要操纵Backbone.Router或直接使用DOM事件。
我已经尝试侦听beforeunload(不起作用,因为应用程序仍在加载)和hashchange(不起作用,因为无法阻止浏览器导航)。这些解决方案(123)在这种情况下不起作用,Javascript从未卸载。
改变 Backbone.Router 似乎是最好的选择,但由于它的初始化方式,我认为引入此功能是不可能的,或者至少我找不到实现的方法。例如,这种解决方案 并不起作用,因为 hashchange 不可取消(无法调用 stopPropagation),而 另一种解决方案 则不起作用,因为 Backbone.Router 对象上未定义 navigate。您有什么建议吗?
1个回答

1
我已经找到了一个解决方案,但还需要更多的工作。对于这个解决方案,我假设您在跟踪视图何时变脏。
有四种主要的离开视图的方式:
  1. 点击视图上的链接
  2. 点击视图外的链接
  3. 点击刷新或外部链接
  4. 在浏览器上点击后退/前进
1. 应用链接 这是最简单的情况。当您点击自己的链接时,必须检查视图是否变脏。例如,我有一个应用内返回按钮,由 historyBack 函数处理。在视图中:
historyBack: function() {
    if (this.isDirty) {
         answer = confirm("There are unsaved changes.\n\nDo you wish to continue?")

        if (answer) {
            this.isDirty = false
            window.history.back()
        }
    }

    else {
        window.history.back()
    }
}

2. 视图外的链接

这种交互可以通过扩展 Router 原型的 execute 方法来处理,而不是像其他地方建议的使用 navigate 方法。

应该有一个变量在 Router 中可访问,用于存储视图状态。在我的情况下,我使用 Router 本身,并在每次更改视图的脏标志时更新此变量。

代码应该类似于:

_.extend(Backbone.Router.prototype, {

    execute: function (callback, args, name) {
        if (Backbone.Router.isDirty) {
            answer = confirm "There are unsaved changes.\n\nDo you wish to continue?";

            if (!answer) {
                return false;
            }
        }

        Backbone.Router.isDirty = false
        if (callback) callback.apply(this, args) 
    }
}

3. 刷新或外部链接

刷新和外部链接会卸载您的Javascript,因此基于beforeunload(见问题)的解决方案实际上是有效的。无论您在哪里管理视图,我使用控制器,但假设它在同一个视图上,您可以在显示时添加监听器,在销毁时删除它:

onShow: function() {
    $(window).bind("beforeunload", function (e) {
        if (this.isDirty) {
             return "There are unsaved changes.";
        }
    }
}

onDestroy: function() {
    $(window).unbind("beforeunload");
}

4. 浏览器的后退/前进功能

这是最棘手的情况,我还没有完全弄清楚。当点击后退/前进按钮时,用户可以在应用内或应用外导航,代码1和3都涵盖了这两种情况,但有一个问题我无法解决,我将创建另一个问题来解决它。

在点击后退/前进按钮时,浏览器会在调用路由器之前更改地址栏,因此您会得到不一致的状态:地址栏显示的路由与应用程序状态不同。如果用户在保存或放弃更改后再次点击后退按钮,则会被带到另一个路由,而不是先前的路由,这是一个大问题。

其他所有内容都正常工作,它会显示一个弹出窗口,询问用户是否要离开或继续,并且如果用户选择留下,则不会重新加载视图。


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