angular跨文件注入服务

新手上路,请多包涵

假设在 a.js 定义了 service A,b.js 定义了一个 controller B,如何在B中注入服务A

阅读 4.6k
3 个回答

angular跨文件注入服务?
看你这个问题,我觉得题主是概念不清楚,应该明白以下基本概念。
1. 你所写的angular代码的组织结构不是以文件来划分的。
2. angular已经抽象成了controller,service,directive等组件。这些东西你可以分成多个文件写,也可以全写在一个文件中,想让你的代码生效,只要在html中加载。为了程序可读性好,我们一般规定一个组件定义时单独放一个文件,并遵循良好的目录结构。
3. 代码划分是靠模块来做的。比如你用bower安装了某个包,你需要在定义你的module时,写入依赖模块,那么这个被依赖模块中定义的组件就有效。这一点谈论的是模块级别的。
4. 何为注入服务?虽然你加载了某个模块,它内部的代码都加载了。但是每个controller依赖哪些服务,angular要如何去找,你还要告诉angular,这时候就需要依赖注入了。这一点谈论的是controller级别的。

综上所述,你就这样 controllerX.$inject = ['serviceX']; 直接最普通的方式加载就行了。
如果没有生效,那应该是以下原因:
1. 没有引入js文件。
2. 没有加载这个service所在的模块。angular.module('MyApp',['ModuleX'])就行了。
3. 但要注意此处你自己的模块MyApp使用可以多次,但是定义依赖只能一次,否则前后引用的就不是一个模块了。
即你可以

angular.module('MyApp',['ModuleX'])
    . controller('ControllerA', ControllerA);
angular.module('MyApp')
    . controller('ControllerB', ControllerB);

但一定不可以

angular.module('MyApp',['ModuleX'])
    . controller('ControllerA', ControllerA);
angular.module('MyApp',['ModuleX'])
    . controller('ControllerB', ControllerB);

检查下这3点,如果还是不行再继续贴代码讨论吧。

首先这个问题要分两种情况,一种是服务A和控制器B都属于同一个模块,另一种情况是服务A和控制器B都不属于同一个模块。

我首先把代码部分贴出来吧:
首先是index.html,代码如下:

<body ng-app="MyApp">
<h1>依赖注入</h1>
<div ng-controller="MyController as vm">
    <button ng-click="vm.getUsers()">getUsers(依赖同一个模块的服务)</button>
    <button ng-click="vm.getUsers2()">getUsers2(依赖不同模块的服务)</button>
    <div ng-repeat="v in vm.users">{{v.avatar_url}}</div>
    <div ng-repeat="v in vm.users2">{{v.id}}</div>
</div>
</body>

另外注意要在index.html中引入a.js b.js c.js

a.js代码部分如下:

angular.module('MyApp',['MyModule'])
    .controller('MyController', MyController);

MyController.$inject = ['MyService', 'MyService2'];

function MyController(MyService, MyService2){
    var vm = this;
    vm.users = [];
    vm.users2 = [];
    vm.getUsers = getUsers;
    vm.getUsers2 = getUsers2;

    function getUsers(){
        console.log('依赖的是同一个模块的服务');
        MyService.getData()
            .then(function(res){
                vm.users = res.data;
            })
    }

    function getUsers2(){
        console.log('依赖的是不同模块的服务');
        MyService2.getData()
            .then(function(res){
                vm.users2 = res.data;
            })
    }
}

b.js代码部分如下:

angular.module('MyApp')
.service('MyService', MyService);

MyService.$inject = ['$http'];

function MyService($http){
    var url = 'https://api.github.com/users';
    var service = {
        getData: getData
    };

    return service;

    function success(res){
        return res;
    }

    function fail(e){
        console.log(e);
    }

    function getData(){
        return $http.get(url)
            .then(success)
            .catch(fail);
    }
}

c.js代码部分如下:

angular.module('MyModule',[])
    .service('MyService2', MyService);

MyService.$inject = ['$http'];

function MyService($http){
    var url = 'https://api.github.com/users';
    var service = {
        getData: getData
    };

    return service;

    function success(res){
        return res;
    }

    function fail(e){
        console.log(e);
    }

    function getData(){
        return $http.get(url)
            .then(success)
            .catch(fail);
    }
}

另外你也可以到这里看看写的一个demo,就是上面代码的运行结果。

需要注意的就是,如果是同一个模块的话,直接在控制器中注入这个服务就可以使用了;如果是不同的模块,那么就有必要在主模块中将你要依赖的那个模块注入到我们的主模块中,然后也可以在控制器中使用了。

你看过代码后应该明白的差不多了,如果还有什么不明白的,还可以看看我之前写过的一篇文章,希望可以帮助你。

我想估计是题主不明白 angularjs 里的数据模型(Model)和视图(View)之间是通过控制器 (controller) 发生数据双向绑定(Data Binding)关系。

data bingding

一个数据模型(M)可以有多个视图(V),也就是说一个控制器(C)可以控制多个视图。这些视图之间可能有业务逻辑之间的关系,为此创建多个控制器,以致让一个控制器控制一个视图。然而这些控制器也有可能有相同的内容,可以提取出来。那么有两种方式:

方式一(继承方式,常见糟糕情况): 多个控制器继承通用的控制器。
方式二(angularjs的service): 将通用的内容提取为一个或多个service,让控制器调用(按需调用不同的service)

可以对比一下两种, service 更具模块化,更有复用性。

我想,这样了解了这一过程,大概就知道楼上说的 依赖注入服务 啦。

宣传栏