【问题标题】:Prevent user to navigate away with unsaved changes阻止用户使用未保存的更改离开
【发布时间】:2023-04-01 16:39:01
【问题描述】:

我目前正在使用 Backbone.Marionette 创建一个 SPA,在其中一个视图中,用户可以通过未保存的更改导航离开。我可以控制其中一些事件,例如视图中的按钮和菜单选项,它们会带走用户,但其他一些则需要操作 Backbone.Router 或直接使用 DOM 事件。

我已经尝试收听beforeunload(由于应用程序仍在加载中不起作用)和hashchange(不起作用,因为您无法阻止浏览器导航离开)。这些解决方案(123)在这种情况下不起作用,Javascript 永远不会被卸载。

更改 Backbone.Router 似乎是最好的选择,但由于它的初始化方式,我认为不可能引入此功能,或者至少我找不到这样做的方法。例如,This solution 不起作用,因为 hashchange 不可取消(您不能对其调用 stopPropagation),而 this other solution 不起作用,因为在 Backbone.Router 对象上未定义 navigate

有什么建议吗?

【问题讨论】:

    标签: javascript jquery backbone.js


    【解决方案1】:

    我已经设法找到了解决方案,尽管还需要做一些工作。对于此解决方案,我假设您在视图脏时进行跟踪。

    有 4 种主要的移出视图的方式;

    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。视图之外的链接

    这种类型的交互可以通过扩展路由器原型的execute 方法来处理,而不是其他地方建议的navigate 方法。

    应该有一个存储视图状态的路由器可以访问的变量。就我而言,我使用的是路由器本身,每次更改视图上的脏标志时都会更新此变量。

    代码应如下所示:

    _.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 的解决方案(请参阅问题)实际工作。无论您在哪里管理视图,我都使用控制器,但我们假设它在同一个视图上,您​​在 show 上添加一个侦听器并在销毁时将其删除:

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

    4.在浏览器上后退/前进

    这是最棘手的情况,也是我尚未完全弄清楚的情况。后退/前进时,用户可以导航出应用程序或在应用程序内导航,这两种情况都包含在 1 和 3 的代码中,但是有一个问题我无法弄清楚,我将为其创建另一个问题.

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

    其他一切正常,它会显示一个弹出窗口,询问用户是要离开还是继续,如果用户选择留下,则不会重新加载视图。

    【讨论】:

      猜你喜欢
      • 2018-05-18
      • 2016-06-25
      • 2019-06-18
      • 1970-01-01
      • 2017-12-30
      • 2020-06-11
      • 2010-11-23
      • 1970-01-01
      • 2019-03-21
      相关资源
      最近更新 更多