如何从父控制器注入依赖?Angular的$routeProvider路由注入示例
嘿,我来帮你搞定AngularJS里从父控制器向子控制器注入依赖的问题!根据你现在用$routeProvider的情况,我分不同场景给你具体方案:
场景1:DOM层级嵌套的父/子控制器(比如嵌套的
ng-controller) 这种情况是子控制器直接在父控制器的DOM作用域下,核心思路是利用AngularJS的作用域继承特性。
方法1:通过$scope共享依赖(简单直接)
父控制器把需要传递的依赖或数据挂载到自身的$scope上,子控制器可以通过$scope直接访问这些内容。注意:如果传递的是基本类型(字符串、数字),会有作用域遮蔽问题,建议把数据封装成对象传递。
父控制器代码:
angular.module("someModule") .controller("ParentController", ParentController); ParentController.$inject = ["$scope", "someServiceDependency"]; function ParentController($scope, someServiceDependency) { // 把服务实例挂载到$scope $scope.parentService = someServiceDependency; // 把resolve风格的异步结果挂载到$scope $scope.parentResolvedData = someServiceDependency.someCall(); }
子控制器代码:
angular.module("someModule") .controller("ChildController", ChildController); ChildController.$inject = ["$scope"]; function ChildController($scope) { // 直接访问父控制器$scope上的依赖 const parentService = $scope.parentService; const parentData = $scope.parentResolvedData; // 这里就可以用这些依赖做业务逻辑了 }
对应DOM结构:
<div ng-controller="ParentController"> <div ng-controller="ChildController"> <!-- 子控制器的视图内容 --> </div> </div>
方法2:用controllerAs语法+原型继承(更推荐,避免$scope污染)
如果你习惯用controllerAs语法(就像你代码里的controllerAs: "vm"),可以把依赖挂载到控制器实例上,子控制器通过$scope访问父控制器的实例。
父控制器代码:
angular.module("someModule") .controller("ParentController", ParentController); ParentController.$inject = ["someServiceDependency"]; function ParentController(someServiceDependency) { const vm = this; // 把依赖挂载到控制器实例 vm.parentService = someServiceDependency; vm.parentResolvedData = someServiceDependency.someCall(); }
子控制器代码:
angular.module("someModule") .controller("ChildController", ChildController); ChildController.$inject = ["$scope"]; function ChildController($scope) { const vm = this; // 通过$scope访问父控制器的实例(假设父控制器别名是parentVm) vm.inheritedService = $scope.parentVm.parentService; vm.inheritedData = $scope.parentVm.parentResolvedData; }
对应DOM结构:
<div ng-controller="ParentController as parentVm"> <div ng-controller="ChildController as childVm"> <!-- 子控制器的视图内容 --> </div> </div>
场景2:路由嵌套的父/子控制器(基于
$routeProvider) 因为原生ngRoute没有真正的嵌套路由支持,我们可以通过共享服务来实现父路由控制器向子路由控制器传递依赖。
步骤1:创建一个共享服务
这个服务用来存储和传递父控制器的依赖:
angular.module("someModule") .factory("SharedDependencyStore", SharedDependencyStore); function SharedDependencyStore() { const store = {}; return { // 存入依赖 set: function(key, value) { store[key] = value; }, // 获取依赖 get: function(key) { return store[key]; } }; }
步骤2:父路由配置+控制器存入依赖
在父路由的resolve里获取依赖,然后存入共享服务:
// 父路由配置 $routeProvider.when("/parent", { templateUrl: "/parent/html", controller: "ParentController", controllerAs: "vm", resolve: { parentResolvedData: ["someServiceDependency", function(someServiceDependency) { return someServiceDependency.someCall(); }] } }); // 父控制器 angular.module("someModule") .controller("ParentController", ParentController); ParentController.$inject = ["parentResolvedData", "SharedDependencyStore"]; function ParentController(parentResolvedData, SharedDependencyStore) { const vm = this; // 把resolve的结果存入共享服务 SharedDependencyStore.set("parentData", parentResolvedData); // 也可以存入服务实例 SharedDependencyStore.set("someService", someServiceDependency); }
步骤3:子路由配置+控制器获取依赖
子路由的控制器注入共享服务,直接取出父控制器存入的依赖:
// 子路由配置(父路由路径为/parent,子路由为/parent/child) $routeProvider.when("/parent/child", { templateUrl: "/child/html", controller: "ChildController", controllerAs: "vm" }); // 子控制器 angular.module("someModule") .controller("ChildController", ChildController); ChildController.$inject = ["SharedDependencyStore"]; function ChildController(SharedDependencyStore) { const vm = this; // 从共享服务获取父控制器传递的依赖 vm.parentData = SharedDependencyStore.get("parentData"); vm.someService = SharedDependencyStore.get("someService"); }
额外:如果用ui-router(更适合嵌套路由场景)
如果项目可以切换到ui-router,它支持原生的状态继承,子状态可以直接继承父状态的resolve依赖,不用额外写共享服务:
// 父状态配置 $stateProvider.state("parent", { url: "/parent", templateUrl: "/parent/html", controller: "ParentController", controllerAs: "vm", resolve: { parentResolvedData: ["someServiceDependency", function(someServiceDependency) { return someServiceDependency.someCall(); }] } }); // 子状态配置,自动继承父状态的resolve $stateProvider.state("parent.child", { url: "/child", templateUrl: "/child/html", controller: "ChildController", controllerAs: "vm" }); // 子控制器直接注入父状态的resolve依赖 ChildController.$inject = ["parentResolvedData"]; function ChildController(parentResolvedData) { const vm = this; vm.parentData = parentResolvedData; }
总结
- DOM嵌套控制器:优先用
controllerAs+原型链,避免$scope污染; - 路由场景:用共享服务适配
$routeProvider,用ui-router的状态继承更简洁; - 尽量别用
$rootScope传递依赖,会造成全局污染,不利于代码维护。
内容的提问来源于stack exchange,提问作者jparaya
相关产品推荐
相关产品推荐

