【问题标题】:Access Angular route scope property $resolve within controller instead of view在控制器而不是视图中访问 Angular 路由范围属性 $resolve
【发布时间】:2016-02-25 20:40:14
【问题描述】:

AngularJS 1.5.0 带来了 $resolve 属性,旨在更轻松地将 ngRoute 解析数据传递到视图中,而无需为指令创建控制器。此属性也适用于常规视图。所以这行得通:

(function() {
  function ConfigureRoutes($routeProvider) {
    $routeProvider.
      when('/test', {
        templateUrl: 'test.html',
        controller: 'TestController',
        controllerAs: 'vm',
        resolve: {
          'stuff': ['$q', function($q) {
            return $q.when([
              { id: 1, name: 'John' },
              { id: 2, name: 'Jake' }
            ]);
          }]
        });
      }
      app.config(['$routeProvider', ConfigureRoutes]);
})();


<pre>{{ $resolve.stuff | json }}</pre>

但是,有时我想将几个解析函数传递给控制器​​以在视图中使用之前进行变异。目前我在做类似的事情:

when('/test', {
  ...
  resolve: {
    'stuff_1': ...
    'stuff_2': ...
  }
});

app.controller('StuffController', ['stuff_1', 'stuff_2', function(stuff_1, stuff_2) {
  this.stuff_1 = stuff_1;
  this.stuff_2 = stuff_2;
}]);

有没有一种方法可以访问这个新的 $resolve 属性而不必单独访问参数?我试过了:

app.controller('StuffController', ['$scope', function($scope) {
  this.stuff_1 = $scope.$resolve.stuff_1; // $scope.$resolve == undefined
}]);

app.controller('StuffController', ['$resolve', function($resolve) {
  this.stuff_1 = $resolve.stuff_1; // injector error
}]);

编辑:

对于将来可能会发现这一点的人,您可以在控制器中以不同的方式访问此 $resolve 对象:

app.controller('TestController', function($route) {
  this.$resolve = $route.current.locals;
});

因此决定在控制器实例化之前不附加$resolve

还决定不制作$resolve 和可注射。这可以使用 $q.all() 作为单个解析函数来实现,如下所示:

function config($routeProvider) {
  $routeProvider.when('/',
    controller: 'TestController',
    controllerAs: 'vm',
    template: 'test.html',
    resolve: {
      $resolve: function($q) {
        return $q.all({
          local_1: $q.when(),
          local_2: $q.when()
        });
      }
    });
}

或者,如果您想要一个分叉版本,请参阅 PR ($scope.$resolve 在控制器之前)[https://github.com/angular/angular.js/pull/14135]

($resolve 为可注入) [https://github.com/angular/angular.js/pull/14136]

【问题讨论】:

    标签: angularjs ngroute


    【解决方案1】:

    在调用控制器和将$resolve 属性置于作用域之间显然存在延迟。

    angular.module("myApp").controller("test", function($scope, $timeout) {
        var vm = $scope;
        console.log("test controller")
        //console.log(vm);
        console.log("$resolve=",$scope.$resolve);  //Undefined
        $timeout(function() {
             console.log("timeout $resolve");
             console.log("$resolve=",$scope.$resolve); //Defined
        });
    });
    

    使用$timeout,值解析。

    DEMO on JSFiddle


    $watch 为例

    angular.module("myApp").controller("test", function($scope) {
        var vm = $scope;
        console.log("test controller")
        console.log(vm);
        console.log("$resolve=", $scope.$resolve); //Undefined
        $scope.$watch("$resolve", function(value) {
             console.log("watch $resolve");
             console.log(value); //Defined
        });
    });
    

    使用$watch,值解析。

    DEMO on JSFiddle


    源代码回顾

    ngView.js Line #273 中,控制器被实例化。

    ngView.js Line #280 中,$resolve 属性被置于作用域内。

    这是一个错误。没有理由不能将$resolve 属性放在控制器被实例化之前的范围内。


    来自 GitHub:

    feat(ngView): 在#13400 范围内引用解析的本地变量

    路由的所有解析现在都附加到路由的本地范围, 作为其名称由 resolveAs 属性给出的属性 路由定义。

    如果未指定resolveAs,则默认为$resolve

    这将使ngRoute 更易于使用,因为它能够引用所有 路由的解析值,直接在作用域上,而不是 实现一个控制器只是为了手动复制解析。

    例如,而不是

    $routeProvider.when('/', {
      resolve: {
        item1: ($http) => $http.get(...),
        item2: ($http) => $http.get(...)
      },
      template: '<my-app item1="vm.item1" item2="vm.item2"></my-app>',
      controllerAs: 'vm',
      controller: ['item1', 'item2', function(item1, item2) {
        this.item1 = item1;
        this.item2 = item2;
      }]
    });
    

    现在可以做

    $routeProvider.when('/', {
      resolve: {
        item1: ($http) => $http.get(...),
        item2: ($http) => $http.get(...)
      },
      template: '<my-app item1="$resolve.item1" item2="$resolve.item2"></my-app>'
    });
    

    【讨论】:

    • 我知道这里有些问题 - 正如您所展示的,文档指出将其用于 $routeProvider 配置中声明的指令,但我找不到任何使用它的示例我想要的典型控制器视图场景。我希望我可以为您在源代码中所做的工作添加更多的赞成票。我瞥了一眼那里,但没有深入了解,我猜。我会提交一个错误。如果注入器可以简单地使用$resolve,那就太好了,所以我不需要注入整个$scope。当this 成为范围时设置this.$resolve = $scope.$resolve 似乎很奇怪......
    • 很容易将$resolve 添加到控制器的注入本地列表中。这是个好主意。在提交 new AngularJS Issue 时包含该建议。
    • 遗憾的是,请参阅This fiddle - 使用 $timeout 值将传播到控制台,但仍然不会传播到视图
    • 看我的例子$watch
    • 我提交了issuepull request 来解决时间问题。我还准备好了代码,可以将$resolveresolveAs 注入控制器中——只是等待他们是否希望我合并或分离这两个 PR 的答案。感谢您的帮助@georgeawg
    猜你喜欢
    • 2016-01-25
    • 1970-01-01
    • 1970-01-01
    • 2017-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-21
    • 1970-01-01
    相关资源
    最近更新 更多