Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
wangsiyuan0215 opened this issue Jan 7, 2020 · 0 comments
Open

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

wangsiyuan0215 opened this issue Jan 7, 2020 · 0 comments

Comments

@wangsiyuan0215
Copy link
Owner

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 针对注入功能的不同提供了一些简写方法:

  • provider
  • factory
  • service
  • constant
  • value
  • decorator

本文的主要内容仅针对 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 里注入服务,不过有些区别:

  • provider 的使用方式最灵活,既可以访问其构造函数内部的成员方法,也可以以调用的方式直接访问 $get 属性,当然也可以使用 new 关键字实例化 $get(前提是 $get 对应的是构造函数);
  • factoryconfig 中只能访问其 $get 方法,并且仅能以函数调用的方式获取 $get 方法的返回值,其值为声明 factory 时的方法;
  • serviceconfig 中也只能访问 $get 方法,但是必须要以 new 关键字来创建实例后访问其实例对象。

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

  • 三者的使用方式相同,没有区别;
  • 需要注意的是 provider,无法在 controllercomponent 中访问构造函数的成员对象,只能访问调用 $get 方法后的返回值。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant