Angular ngRoute/UI-Router 奇怪的重定向行为

Angular ngRoute/UI-Router strange redirect behaviour

我有一个 angular 应用程序,它由一个 index.html 页面组成,里面有一些部分视图。假设有 4 个局部视图:view1、view2、view3 和 view4。当您第一次点击我的 home/root 页面时,我希望 View1 成为加载到 index.html 中的基本视图。我通过将我的 $urlRouterProvider.otherwise() 设置为我的 view1 部分来做到这一点。

出于某种原因,此问题仅针对特定视图发生。假设它是view3。当我单击 view3 上的按钮时,它应该路由到另一个视图,比如 view4。它总是第一次成功路由。但是,每当我通过任何方法 return 到 view3 并尝试在第一个之后的任何时间路由到 view4 时,它总是强制路由回到 $urlRouterProvider.otherwise() 中的任何视图:在这种情况下它是 view1。也不只是 view4。无论我尝试从 view3 路由到哪个视图,它都会在第一次成功加载该视图,然后在它始终默认为 $urlRouterProvider.otherwise() 视图后的任何时间加载。

更奇怪的是,即使它强制路由到 otherwise(),我知道我试图路由到的任何部分的 controller/view 正在加载。如果我将 $urlRouterProvider.otherwise() 设置为我的应用程序中不存在的路由,然后重现这种奇怪的行为,结果是 url 显示为 'localhost:8080/routeThatDoesNotExist',但实际上是什么屏幕上显示的是我试图路由到的视图。这是我的代码的简洁版本:

app.js:

var app = angular.module('app', ['ui.router', 'controllers','services']);

app.config(['$stateProvider', '$urlRouterProvider', '$locationProvider',
                    function($stateProvider, $urlRouterProvider, $locationProvider) {
                      $urlRouterProvider.otherwise("/");
                      $stateProvider.
                        state('root', {
                          url: "/",
                          templateUrl: 'partials/view1.html',
                          controller: 'View1Ctrl',
                        }).
                        state('view2', {
                          url: "/view2",
                          controller: 'View2Ctrl',
                          templateUrl: 'partials/view2.html'
                        }).
                        state('view3', {
                          url: "/view3",
                          controller: 'View3Ctrl',
                          templateUrl: 'partials/view3.html',
                        }).
                        state('view4', {
                          url: "/view4",
                          templateUrl: 'partials/view4.html',
                          controller: 'View4Ctrl',
                        });
                        //more views omitted for brevity...
                        $locationProvider.html5Mode(true);
                    }]);

Index.html

<!doctype html>
<html ng-app="app">
<head>
    <base href="/">
    <title>App</title>
    <link rel="...">
    <style>...</style>
</head>

<body>

<div ng-controller="IndexDotHtmlCtrl">
        <button ui-sref="root">View1</button>
        <button ui-sref="view2">View2</button>
        <button ui-sref="view3">View3</button>
        <div ui-view></div>
</div>
<script src="..."></script>
</body>
</html>

View3.html

<div>
    <button ng-click="stateGo()">Go To Another View</button>
</div>

Controllers.js

var controllers = angular.module('controllers', []);

controllers.controller('IndexDotHtmlCtrl', ['$scope', function($scope) {
    //code omitted...
}]);

controllers.controller('View1Ctrl', ['$scope', '$state', function($scope, $state) {
    //code omitted...
}]);

controllers.controller('View2Ctrl', ['$scope', '$state', function($scope, $state) {
    //code omitted...
}]);

controllers.controller('View3Ctrl', ['$scope', '$state', function($scope, $state) {

   $scope.stateGo = function() {
       $state.go('view4');
   }
   //more code omitted...

}]);

controllers.controller('View4Ctrl', ['$scope', '$state', 'SomeSvc', function($scope, $state, SomeSvc) {

    $scope.RESTful_DATA = SomeSvc.query(); //using ngResource
    //more code omitted...

}]);

我尝试做的事情: 我最初使用 Angular 的 ngRoute 遇到这个问题,所以我将我的整个应用程序移到了 Angular UI-路由器问题仍然存在。

认为 $locationProvider 和 html5Mode 可能与此有关。删除了将 # 添加到我的 url 的那些。问题仍然存在。

总而言之,问题是,每当我尝试专门从 view3 路由到我的应用程序中的任何其他视图时,它总是在第一次工作。之后的任何时候,它都会调用 $urlRouterProvider.otherwise() 方法并强制将我重定向到我在其中定义的任何视图。我不确定此时该做什么。谁能帮我弄清楚为什么会出现这种奇怪的路由行为?

在研究了 Whosebug 和 github 之后,我发现问题与 ngRoute/Ui-router 服务本身无关。问题在于我在项目中使用的 <uib-tabset><uib-accordion> 指令模板。它们是 Angular Ui-Bootstrap 库的一部分。这是一个已知问题,已在 Angular Ui-bootstrap 的 github 上多次提出:例如 here.

如果我理解正确的话,本质上发生的事情是这些 <uib-tabset><uib-accordion> 获得 <a> 附加到它们的锚标记。这意味着,如果您的 tabset 或手风琴中有任何可点击的元素(基本上,纯文本以外的任何元素),angular 永远不会收到它们的点击事件。它们被浏览器拦截,导致奇怪的重定向行为发生。这解释了为什么我只有特定视图的奇怪路由行为,而不是我应用程序中的所有视图。

Angular Ui-Bootstrap 团队 here 提出的当前修复(向下滚动几格,在屏幕右下角附近查看 'Known Issues' header 并阅读该部分)是修改 tabset 和 accordion 指令模板本身,将它们插入 <a> 锚标记的位置更改为 <div> 标记。这样做会导致您丢失大部分关联的 CSS 样式,因为它们基于 <a> 元素。从这里,只需转到您的 bootstrap.css,找到所有影响 uib-tab 和 uib-accordion 的 CSS 规则,然后更新它们,使它们指向 div 而不是一.