如何使用angular检测浏览器后退按钮单击事件?

Tho*_*mel 79 javascript jquery angularjs

是否可以通过浏览器中的历史记录返回按钮检测用户是否输入了页面?我最好想用angular.js检测这个动作.

我不想使用角度路由.如果用户提交表单并在成功提交到服务器并重新定向之后,它也应该有效,如果用户使用浏览器的后退按钮返回到表单,也应该可以.

Ber*_*and 119

这是Angular的解决方案.

myApp.run(function($rootScope, $route, $location){
   //Bind the `$locationChangeSuccess` event on the rootScope, so that we dont need to 
   //bind in induvidual controllers.

   $rootScope.$on('$locationChangeSuccess', function() {
        $rootScope.actualLocation = $location.path();
    });        

   $rootScope.$watch(function () {return $location.path()}, function (newLocation, oldLocation) {
        if($rootScope.actualLocation === newLocation) {
            alert('Why did you use history back?');
        }
    });
});
Run Code Online (Sandbox Code Playgroud)

我正在使用一个运行块来启动它.首先,我将实际位置存储在$ rootScope.actualLocation中,然后我监听$ locationChangeSuccess,当它发生时,我用新值更新actualLocation.

在$ rootScope中我监视位置路径的变化,如果新位置等于previousLocation是因为没有触发$ locationChangeSuccess,这意味着用户已经使用了历史记录.

  • 对于任何不理解它如何工作的人(比如我):当url以通常的方式更改(不使用后退/前进按钮)时,然后在$`$ watch`回调之后`$ locationChangeSuccess`事件触发**.但是当url使用后退/前进按钮或`history.back()`api进行更改时,那么`$ locationChangeSuccess`事件会在**`$ watch`回调之前触发**.因此,当看回调触发`actualLocation`已经等于`newLocation`时.这就是内部角度的工作原理,这个解决方案只是使用了这种内部行为. (19认同)
  • 上面的代码不会检测URL查询字符串更改,例如从`/#/ news /?page = 2`到`/#/ news /?page = 3`.要捕获它们,你可以使用`$ location.absUrl()`而不是`$ location.path()`(在上面使用它的两个地方). (5认同)
  • 没错.从来没有使用过角度路线,所以看你的例子似乎没有正常的和非正常的(角度路线类型)超链接.所以忘记我的评论.. (4认同)
  • $ locationProvider.html5Mode(true)仅用于使链接在jsFiddle中工作,您在项目中不需要它.只需记住链接需要以#/开头,因此angular可以捕获它们(在小提琴中它们不是).如果您使用"普通"链接,像/ book,angular这样的内容将无法捕获它,并且页面将被重定向到该URL,这将重置您的应用程序,因为所有脚本都将重新加载,这就是为什么它不起作用的原因. (2认同)

小智 11

如果您想要更精确的解决方案(检测后退和前进),我将通过Bertrand提供的扩展解决方案:

$rootScope.$on('$locationChangeSuccess', function() {
    $rootScope.actualLocation = $location.path();
});


$rootScope.$watch(function () {return $location.path()}, function (newLocation, oldLocation) {

    //true only for onPopState
    if($rootScope.actualLocation === newLocation) {

        var back,
            historyState = $window.history.state;

        back = !!(historyState && historyState.position <= $rootScope.stackPosition);

        if (back) {
            //back button
            $rootScope.stackPosition--;
        } else {
            //forward button
            $rootScope.stackPosition++;
        }

    } else {
        //normal-way change of page (via link click)

        if ($route.current) {

            $window.history.replaceState({
                position: $rootScope.stackPosition
            });

            $rootScope.stackPosition++;

        }

    }

 });
Run Code Online (Sandbox Code Playgroud)


小智 8

对于ui-routing,我使用下面的代码.

在里面App.run(),使用

 $rootScope.$on("$stateChangeStart", function (event, toState, toParams, fromState, fromParams) 
 {

    if (toState.name === $rootScope.previousState )
       { 
          // u can any 1 or all of below 3 statements
         event.preventDefault();  // to Disable the event
         $state.go('someDefaultState'); //As some popular banking sites are using 
         alert("Back button Clicked");

       }
 else
      $rootScope.previousState= fromState.name;
   });
Run Code Online (Sandbox Code Playgroud)

你可以在"$ stateChangeSuccess"事件'previousState的价值也一样,如果`你要如下.

    $rootScope.$on("$stateChangeSuccess", function (event, toState, toParams, fromState, fromParams) 
   {

        $rootScope.previousStatus = fromState.name;
    });
Run Code Online (Sandbox Code Playgroud)