wangsiyuan0215 / blog

Personal blog as F2E for recoding issues in my jobs and harvest in my daily life.
5 stars 0 forks source link

《深入理解 AngularJs 之 $provider》 #14

Open wangsiyuan0215 opened 4 years ago

wangsiyuan0215 commented 4 years ago

1. 什么是 $provider

$provider 是 AngularJs 的提供的一种服务(service),基于 $injector 模块将许多方法注册到组件、config 和 filter 中。

那什么是 AngularJs 的 service 呢?

AngularJs 的 service 是基于 service 工厂创建出来的单一对象,而 service 工厂均是由 service provider 创建的。service provider 是一个构造函数,当 service provider 被实例化的时候,一定会包含 $get 属性,这个属性就是 service factory 所要提供的所有方法的函数。

$provider 在调用时发生了什么?

当在 controller 或者是 component 中引用 $provider 的时候,$injector 会根据 name 找到正确的 $provider ,然后实例化它、调用 $get 并返回他的值,而这个值就是 service 的实例。

2. $provider 有哪些表现形式?

$provider 针对注入功能的不同提供了一些简写方法:

本文的主要内容仅针对 service , factoryprovider 这三种形式的 $provider

3. 如何使用?

若要 $provider 生效,那么需要将其挂在到某一个 module 下:

var demo = angular.module('DemoModule');

本文将以 var demo 作为主要的演示模块。

3.1 provider(name, constructor)

注册一个 provider 的构造函数,通过实例化这个构造函数可以注入 factory 或 service

可以理解为,factoryservice$provider 都是在 provider 方法基础上做的进一步封装。


// 声明名为 test4provider 的 provider
demo.provider('test4provider', function () {
    // 赋予 test4provider 构造函数一个成员方法 sayHello
    this.sayHello = function () {
        console.log('test4provider say hello');
    };

    // $get 方法赋值是必不可少的,这是该 provider 可注入到其他 controller 或 component 的先决条件
    this.$get = ['$scope', function ($scope) {
        return {
            sayHi: function () {
                console.log('test4provider\'s $get say hi!');
            }
        };
    }]
})

demo.config('demo.config', ['test4providerProvider', function (test4provider) {
    // { sayHello: function() {...}, $get: function() { ... } }
    console.log(test4provider);

    // test4provider say hello
    test4provider.sayHello();

    // test4provider's $get say hi!
    test4provider.$get().sayHi();

}])

demo.controller('demo.ctrl', ['test4provider', function(test4provider) {
    // Error: sayHello is not a function
    test4provider.sayHello();

    // 调用 test4provider 的服务项 sayHi
    test4provider.sayHi();
}])

3.2 factory(name, $getFn)

注册 factory 的服务。


// 声明名为 test4factory 的 factory
demo.factory('test4factory', function () {
    return {
        sayHi: function () {
            console.log('test4factory\'s $get say hi!');
        }
    };
})

demo.config('demo.config', ['test4factoryProvider', function (test4factory) {
    // { $get: function() { ... } }
    console.log(test4factory);

    // Error: sayHello is not a function
    test4provider.sayHello();

    // test4factory $get say hi!
    test4factory.$get().sayHi();

}])

demo.controller('demo.ctrl', ['test4factory', function(test4factory) {
    // Error: sayHello is not a function
    test4factory.sayHello();

    // 调用 test4factory 的 sayHi
    test4factory.sayHi();
}])

3.3 service(name, constructor)

注册服务的构造函数。


var Say = function () {};

Say.$inject = ['$scope'];

Say.prototype.sayHi = function () {
    console.log('Say hi!');
};

// 声明名为 test4service 的 service
demo.service('test4service', Say);

demo.config('demo.config', ['test4serviceProvider', function (test4service) {
    // { $get: function() { ... } }
    console.log(test4service);

    // Error: sayHello is not a function
    test4service.sayHello();

    // 通过 new 关键字创建一个 test4service 的 $get 的实例,然后调用 sayHi 方法
    (new test4service.$get()).sayHi();  // say hi!
}])

demo.controller('demo.ctrl', ['test4service', function(test4service) {
    // Error: sayHello is not a function
    test4service.sayHello();

    // 调用 test4service 的原型方法 sayHi
    test4service.sayHi();
}])

4. 总结

OK,到这里你可能对 provider, factoryservice 有了大致的了解,那么让我们来总结下:

1. 这三种方法都可以在 config 里注入服务,不过有些区别:

2. 这三种方法都可以在 controllercomponent 中注入服务: