【问题标题】:Angular UI-Router Abstract Parent state resolve dataAngular UI-Router 抽象父状态解析数据
【发布时间】:2015-11-28 20:08:56
【问题描述】:

我有以下ui-router状态配置:

angular
.module('my_app', ['ui.router'])
.config(function($stateProvider, $urlRouterProvider, $locationProvider){
    $urlRouterProvider.otherwise('/');
    $stateProvider
    .state('main', {
        abstract: true,
        views: {
            "header": {
                templateUrl: "app/views/shared/header.html",
                controller: "MainController",
                controllerAs: "main"
            },
            "content": {
                template: "<ui-view />"
            }
        },
        resolve: {
            mobile: mobileCheck
        }
    })
    .state('main.home', {
        url: '/',
        templateUrl: 'app/views/templates/home.html',
        controller: 'HomeController',
        controllerAs: 'home',
    })
    .state('main.earn', {
        url: '/earn',
        templateUrl: 'app/views/templates/earn.html',
        controller: "EarnController",
        controllerAs: 'earn',
    })
    .state('main.vision', {
        url: '/vision',
        templateUrl: 'app/views/templates/vision.html',
        controller: "VisionController",
        controllerAs: "vision"
    })
    .state('main.contact', {
        url: '/contact',
        templateUrl: 'app/views/templates/contact.html',
        controller: "ContactController",
        controllerAs: "contact"
    })
});

在这里,我有一个抽象的父状态main,每个子状态(main.homemain.earn 等)都是应用程序中的不同页面。 抽象状态的存在是为了使用一个通用模板,即标题,高于所有页面模板:

views: {
    "header": {
        templateUrl: "app/views/shared/header.html",
        controller: "MainController",
            controllerAs: "main"
        },
        "content": {
            template: "<ui-view />"
        }
    }

对应的html如下:

<body ng-controller="MainController as main" ng-cloak>
    <div ui-view='header'></div>
    <div ui-view='content'></div>

    <script src="app/app.js"></script>

    <!-- AngularJS Controllers -->
    <script src="app/controllers/mainController.js"></script>
    <script src="app/controllers/homeController.js"></script>
    <script src="app/controllers/earnController.js"></script>
</body>

header 命名视图是注入标头的位置,content 视图包含每个页面模板。

如您所见,我已经在整个文档的正文中定义了主控制器,并为特定页面模板指定了控制器别名,因此我应该能够在任何我能够确认的页面模板有效。

但是,在主控制器中访问我已解析的数据是行不通的。我可以访问每个页面模板,但不能访问主要的“父”控制器。每个页面控制器都通过了mobile 依赖项,然后它可以附加到this 用于检测移动/桌面环境。我宁愿能够在MainController 中接收mobile 依赖项,但是每当我尝试.controller('MainController', function(mobile) 时,我都会收到有关不正确依赖项注入的标准角度错误。

这让我相信解析数据正在解析到子状态(和控制器),而不是父控制器。我认为这是因为 1)父抽象状态没有 url 和 2)因为该状态的控制器是在主体上命名的,而不是在状态本身上。

我怎样才能将解析的数据作为依赖项解析到我的主控制器中?我尝试在状态配置中命名控制器,但没有效果。

【问题讨论】:

    标签: javascript angularjs templates angular-ui-router


    【解决方案1】:

    我在发布问题后不久就解决了我的问题,但我想我还是应该发布我的发现/答案。

    总结一下我的目标是:

    1. 结合命名和非命名ui-view标签
    2. 将数据解析到父控制器和所有子状态
    3. 在子控制器的 html 模板中访问父控制器和子控制器。

    我将介绍我如何解决从 1 到 3 的每一个问题,所有这些都与如何将数据解析为抽象状态及其子状态的更大问题有关。

    首先,看看我的身体标签:

    <body ng-controller="MainController as main" ng-cloak>
    

    将父控制器定义在 body 标记而不是状态提供程序内部意味着任何解析的数据都不会传递给 body 实例化的 MainController 实例,而是传递到指定的 MainController 实例在我的配置中。无论哪种方式,由于依赖注入问题,主体控制器都会导致应用程序崩溃。

    所以我从正文标签中删除了ng-controller。然后,要同时拥有命名视图和页面注入的常规 &lt;ui-view&gt; 标签,您可以在 index.html 文件中创建两个命名为 ui-views:

    <div ui-view='header'></div>
    <div ui-view='content'></div>
    

    在状态配置中:

    .state('main', {
        abstract: true,
        views: {
            "header": {
                templateUrl: "app/views/shared/header.html",
                controller: "MainController",
                controllerAs: "main"
            },
            "content": {
                template: "<ui-view />"
            }
        },
        resolve: {
            mobile: mobileCheck
        }
    })
    

    共享视图将从指定的 templateURL 加载,页面被注入到命名 content 标记内的 ui-view

    所以在这里我们解决了 1 和 2。我们都有命名视图,同时能够注入页面,并且所有控制器实例都接收到解析的依赖项。但是现在,即使标头可以访问主控制器,content 标记内的任何页面都不能。 不幸的是,将控制器命名为:

    .state('main', {
        controller: "MainController",
        controllerAs: "main",
        views: { ... }
    

    也不行。

    那么简单的技巧就是在所有子视图上定义主控制器:

    views: {
        "header": {
            templateUrl: "app/views/shared/header.html",
            controller: "MainController",
            controllerAs: "main"
        },
        "content": {
            template: "<ui-view />",
            controller: "MainController",
            controllerAs: "main"
        }
    }
    

    现在共享视图可以访问父控制器,子模板可以访问两个控制器。因此,您可以在父控制器上定义公共状态,例如环境是否是移动的,而不是在每个子控制器上定义它。

    注意:

    因为主控制器是在两个地方定义的,所以主控制器被实例化了两次。您可以通过提供某种服务或其他东西并为父控制器提供共享变量来解决此问题

    【讨论】:

      【解决方案2】:

      也许您可以使用您的mobileCheck 提供服务或provider,这样您就不必为您的州解决它?考虑

      .provider('mobileCheck', function mobileCheck() {
        this.$get = function() {
          return {
            isMobile: function() {
              return true;
            }
          };
        };
      })
      
      .controller('MainController', function(mobileCheck) {
        var main = this;
        main.isMobile = mobileCheck.isMobile();
      })
      
      .config(function($stateProvider) {
        $stateProvider
          .state('main', {
            abstract: true,
            views: { 
              'header': {
                template: '<div>abstract state : main (isMobile {{ main.isMobile  }})</div>',
                controller: 'MainController',
                controllerAs: 'main'
              },
              'content': {
                template: '<ui-view />'
              }
            }
          })
          .state('main.home', {
            url: '/',
            template: '<div>concrete state : home  (isMobile {{ main.isMobile  }})</div>',
            controller: angular.noop
          });
      });
      

      像你一样使用 HTML 模板

      <body ng-controller="MainController as main" ng-cloak>
        <div ui-view="header"></div>
        <div ui-view="content"></div>
        <hr>
        <div>
          <a ui-sref="main.home">main.home</a>
        </div>
      </body>
      

      会给你类似的东西

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-05
        • 2014-10-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多