Javascript AngularJS路由取消--为什么我需要使用$rootScope?

Javascript AngularJS路由取消--为什么我需要使用$rootScope?,javascript,angularjs,url-routing,Javascript,Angularjs,Url Routing,我有一个表单,我想防止用户在没有将数据保存回服务器的情况下离开。我从中借用了代码,它允许我向$locationChangeStart事件添加一个侦听器。我把下面的代码放在我表单的控制器中,瞧,什么也没发生 var cancelRouteListener = $rootScope.$on('$locationChangeStart', checkForUnsavedData); function checkForUnsavedData (event, newURL) {

我有一个表单,我想防止用户在没有将数据保存回服务器的情况下离开。我从中借用了代码,它允许我向
$locationChangeStart
事件添加一个侦听器。我把下面的代码放在我表单的控制器中,瞧,什么也没发生

    var cancelRouteListener = $rootScope.$on('$locationChangeStart', checkForUnsavedData);

    function checkForUnsavedData (event, newURL) {
        if (!$scope.form.$dirty) {
            return;
        }

        var proceed = $window.confirm('The page has unsaved changes. Do you want to continue?');

        if (proceed) {
            cancelRouteListener();
            $location.path(newURL);
        }

        event.preventDefault();
        return;
    }
我可以看到代码到达调用
$location.path()
,但是页面导航没有改变。然后,出于绝望,我尝试在对
$rootScope.$apply()
的调用中包装这行代码:

瞧,这是成功的。我有几个问题:

  • 为什么我需要使用
    $apply()
    函数?我原以为代码会在$rootScope的上下文中运行
  • 我真的需要将此附加到
    $rootScope
    ?我只需要在窗体的路由处于活动状态时使用此侦听器

  • 首先,你的意思是不是
    $apply()
    ?其次,为什么要在控制器中使用
    $rootScope
    而不是
    $scope
    来启动摘要循环。第三,我认为您没有使用正确的逻辑来实现所需的功能。事件
    $locationChangeStart
    表示角度应用程序内位置更改的开始
    $window.confirm()
    将在调用
    事件时暂时停止导航。preventDefault()
    将一起停止导航。因此,您应该等待
    $window.confirm()
    的确认。如果使用单击取消,
    继续
    将为false。如果
    procedue
    为false,则调用
    event.preventDefault()
    ,否则不执行任何操作。当应用程序已经在导航到该页面的过程中时,绝对不需要调用
    $location.path()

    我在这里创建了一个场景:


    首先,是的,我的意思是
    $apply()
    。第二,我这么做只是因为这是我遇到的第一个选择——我在这里发帖是因为我认为我不需要这么做,我想知道为什么。第三,我明白你们的逻辑,因为我所做的是多余的。然而,这并不是我想要的答案。
    $rootScope.$apply()
    根本不是必需的,事实上,它甚至不可能实现。如果在控制器中执行此逻辑,则应调用
    $scope.$on
    而不是
    $rootScope.$on
    ,因为
    $locationChangeStart
    是一个广播事件,它向下冒泡到所有子作用域。这将为您节省依赖注入。您不应该被允许这样做,因为事件侦听器总是在摘要周期内被调用。调用
    $apply()
    会使应用程序崩溃。您的控制器是如何定义的?我的控制器是在我的模块对象上使用
    .controller()
    方法定义的——它不在全局名称空间中,如果这是您的意思的话。我想我理解你的意思——在
    $rootScope
    上使用
    $apply()
    可能会导致很多问题。我已经重构了代码以使用控制器的子作用域。这听起来像是我试图遵循一个非常草率的编码示例,所以我将把它归为坏习惯,并从现在开始按照您建议的方式执行。谢谢
    $rootScope.$apply(function () {
        $location.path(newURL);
    }