我爱编程

AngularJS:Service、Factory、Provid

2018-03-16  本文已影响0人  阿羡吖

本篇转载于:http://blog.csdn.net/evankaka
AngularJs GitHub: https://github.com/angular/angular.js/
AngularJs下载地址:https://angularjs.org/
注:代码都亲测过,效果是一样的,所以用了作者原本的图,望谅解

AngularJs中可用来注入的有三种类型,service、factory、provide,这三种写法不一样,用法也不一样,其中,service只实例化一次,其实就是单例模式的思想,无论我们在什么地方注入service,将永远使用同一个实例,所以对很多Controller的操作就可以放到service层中去。
AngularJS提供例如许多的内在服务,如:$http$route$window,$location等等。每个服务负责例如一个特定的任务,$http是用来创建AJAX调用,已获得服务器的数据。$route用来定义路由信息等。内置的服务总是前缀$符号。
关系图如下所示:

image.png

一、Service使用详解
(1)定义
一般使用this来操作数据、定义函数。

app.service('myService', function () {
    var privateValue='I am priivate';
    this.variable = 'This is public';
    this.getPrivate = function(){
        return privateValue;
    };
});

(2)AngularJS中使用DI添加Service的三种方式
方式1(内联注解,推荐使用)

app.controller('myController',['$scope','deteFiler',function($scope,deteFilter){}]);

方式2($inject注解)

var MyController = function($scope,dateFilter){}
MyController.$inject =['$scope','dateFilter'];
someModule.controller('MyController',MyController);

方式3 (隐式注解、不推荐使用);

app.controller('mycontroller',function($scope,dateFilter){});

推荐使用方法1的理由是:
写法上比方法2更简单明了,比方法3更可靠(由于JavaScriptkeyi可以被压缩,AngularJs又是通过解析服务器名称找到对应的Service的,因为JavaScript压缩之后AngularJs将无法找到指定的Service,但字符串不会被压缩,因此单独以字符串指定的Service的名称可以避免这个问题)
使用方法1或方法2的注意点:
由于上述第二点原因:AngularJS在编译Htm时,由$injector将数组中的service的名称与方法中的Service进行--映射。这种映射关系必须遵循由AngularJS的约定:
数组中Service名称的个数必须与方法体中Service名称个数一致
数组中Service的顺序必须与方法体中Service的顺序一致。

(3)什么时候适合使用Service()方法
Service()方法很适合使用在功能控制比较多的Service()里面
*需要使用.config()来配置service的时候不能使用service()方法
(4)service使用实例

<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
    <meta charset="UTF-8">
    <title>AngularJs学习</title>
    <script type="text/javascript" src="js/angular.min.js"></script>
</head>
<body>
    <div ng-controller="MyCtrl">
        <button ng-click="getPrivate()">按钮一</button>
        <button ng-click="getPublic()">按钮二</button>
    </div>
    <div ng-controller="MyCtrl2"></div>
</body>
<script type="text/javascript">
    var app = angular.module('myApp', []);
    app.controller('MyCtrl',function ($scope,myService) {
        $scope.getPrivate = function(){
            alert(myService.getPrivate());
        };
        $scope.getPublic = function(){
            alert(myService.variable);
        };
    });
    app.controller('MyCtrl2',function ($scope,myService) {  
    });
    app.service('myService', function () {
        console.log('instance myService');
        var privateValue = 'I am private';
        this.variable = 'This is public';
        this.getPrivate=function(){
            return privateValue;
        }
    });
</script>
</html>

效果如下:

image.gif
另外,从控制台可以看出两个Controller注入了同一个Service,但最终只实例化了一次。
image.png
service定义的服务不能在.config中使用!只有providerdingyi定义的才可以

二、Factory使用详解
Factory一般就是创建一个对象。然后在这个对象添加方法与数据,最后将些对象返回即可,然后注入到Controller层中即可。
使用实例:

<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
    <meta charset="UTF-8">
    <title>AngularJs学习</title>
    <script type="text/javascript" src="js/angular.min.js"></script>
</head>
<body>
    <div ng-controller="MyCtrl">
        <button ng-click="getPrivate()">按钮一</button>
        <button ng-click="getPublic()">按钮二</button>
    </div>
    <div ng-controller="MyCtrl2"></div>
</body>
<script type="text/javascript">
    var app = angular.module('myApp', []);
    app.controller('MyCtrl',function ($scope,myFactory) {
        $scope.getPrivate = function(){
            alert(myFactory.getPrivate());
        };
        $scope.getPublic = function(){
            alert(myFactory.variable);
        };
    });
    app.controller('MyCtrl2',function ($scope,myFactory) {  
    });
    app.factory('myFactory', function () {
        console.log('instance myFactory');
        var privateValue = 'I am private';
        this.variable = 'This is public';
        this.getPrivate=function(){
            return privateValue;
        };
        return factory;
    });
</script>
</html>

效果如下:


image.gif

另外,从这里可以看到controller注入同一个factory,但是最终只实例化了一次。


image.png
记住一定要return 一个Object对象,否则会报出一下错误。
image.png

三、provider使用详解
$provide服务负责告诉AngularJs如何r创造一个新的可注入的东西,即服务。服务会被叫做供应商的东西来定义,你可以使用$provide来创建一个供应商。你需要使用$provide中的provider()方法来定义一个供应商,同时也可以通过要求$provide被注入到一个引用的config函数中来获得$provide服务,使用方法是返回一个$get函数,注意的是,在config阶段,只有provider能被注入,其他用法和service一样。
实例:

<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
    <meta charset="UTF-8">
    <title>AngularJs学习</title>
    <script type="text/javascript" src="js/angular.min.js"></script>
</head>
<body>
    <div ng-controller="myCtrl1">
        <button ng-click="onclick1()">请点击我1</button>
    </div>
    <div ng-controller="myCtrl2">
        <button ng-click="onclick2()">请点击我2</button>
    </div>
</body>
<script type="text/javascript">
    var app = angular.module('myApp', []);
    app.controller('myCtrl1', function ($scope , testProvider) {
        $scope.onclick1=function(){
            testProvider("林炳文Evankaka");
        };
    });

    app.controller('myCtrl2',function ($scope , testProvider) {
        $scope.onclick2 = function(){
            testProvider("我到底是谁");
        };
    });

    app.provider('testProvider', function () {
        console.log('instance testProvider');
        var f = function(name){
            alert("hello,"+name);
        }
        this.$get = function() {
            return f;
        };
    });
</script>
</html>

效果如下:


image.gif

控制台输出内容:


image.png

下面是一个provider实例化的时间测试

<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
    <meta charset="UTF-8">
    <title>AngularJs学习</title>
    <script type="text/javascript" src="js/angular.min.js"></script>
</head>
<body>
    <div ng-controller="myCtrl1">
        <button ng-click="onclick1()">请点击我1</button>
    </div>
    <div ng-controller="myCtrl2">
        <button ng-click="onclick2">请点击我2</button>
    </div>
</body>
<script type="text/javascript">
    var app = angular.module('myApp', []);

    app.controller('myCtrl1',function ($scope) {
        // $scope.onclick1 = function(){
        //  test("林炳文Evankaka");
        // };
    });
    app.controller('myCtrl2', function ($scope) {
        // $scope.onclick2 = function(){
        //  test("我到底是谁");
        // };
    });

    // app.config(function (testProvider) {
    //  testProvider('I am config');
    // });

    app.provider('test', function () {
        console.log('instance test')
        var f = function(name){
            alert("hello,"+name);
        }

        this.$get = function() {
            return f;
        };
    });

    app.config(function ($provide) {
        $provide.provider('greetting', function(){
            this.$get = function(){
                return function(name){
                    alert('hello,'+name);
                }
            }
        });
        // greetingProvider('ff');
    });
</script>
</html>
image.png

页面刷新后,即使不注入provider,但它也进行了实例化,而Service/Factory则是第一次注入时才会初始化。而这也是为什么它可以注入到config的一个原因吧。

什么时候使用provider() 方法
(1)当我们希望在应用开始前对Service进行配置的时候就需要使用到provider().。比如,我们需要配置Service在不同的部署环境(开发,演示,生产)使用不同的后端处(2)理的时候,就可以使用到了,当我们打算发布开源provider()也是首选创建service的方法,这样就可以使用配置的方法来配置Services而不是将配置数据硬编码写到代码里。

四、Service、Factory、Provider三者的区别

(1)用Factory就是创建一个对象,为它添加属性,然后把这个对象返回出来。把Service传进Controller之后,在Controller里这个对象的属性就可以通过factory使用了。
(2)Service是用new关键字实例化的。因此,应该给this添加属性。然后service返回this,把service传进Controller之后,在Controller里this上的属性就可以通过Service来使用了。
(3)providers是唯一一种可以传入.config()函数的Service。当想要在Service对象启用之前,先进性模块范围的配置,那就应该使用provider
(4)Factory/service是第一个注入时才实例化。而provider不是,它是在config之前就实例化好了。
同一种函数的三种不同写法:

<!DOCTYPE html>
<html lang="en" ng-app="myApp">
<head>
    <meta charset="UTF-8">
    <title>AngularJs学习</title>
    <script type="text/javascript" src="js/angular.min.js"></script>
</head>
<body>
    <div ng-controller="myCtrl1">
        <p>{{ output1 }}</p>
        <p>{{ output2 }}</p>
        <p>{{ output3 }}</p>
    </div>
    <div ng-controller="myCtrl2"></div>
</body>
<script type="text/javascript">
    var app = angular.module('myApp', []);
    app.controller('myCtrl1', function ($scope,testService,testFactory,testProvider) {
        $scope.output1 = testService.lable;
        $scope.output2 = testFactory.lable();
        $scope.output3 = testProvider;
    });

    app.controller('myCtrl2', function ($scope,testService,testFactory,testProvider) {
        
    });

    app.service('testService', function () {
        console.log('instance testService');
        this.lable = 'this is service'; 
    });

    app.factory('testFactory', function () {
        console.log('instance testFactory');    
    
        return {
            lable:function(){
                return 'this is factory';
            }
        };
    });

    app.provider('testProvider', function () {
        console.log('instance testProvider');
        
        this.$get = function() {
            return 'this is provider';
        };
    });
</script>
</html>
image.png

看console的输出,可以知道都只实例 化了一次:


image
上一篇下一篇

猜你喜欢

热点阅读