这里是修真院前端小课堂,每篇分享文从
八个方面深度解析前端知识/技能,本篇分享的是:
【angular js中的依赖注入是什么?有什么作用?与不用依赖注入的其他框架相比,有何优点? 】
1.背景介绍
依赖注入(Dependency Injection,简称DI)是一种软件设计模式,在这种模式下,一个或更多的依赖 (或服务)被注入(或者通过引用传递)到一个独立的对象(或客户端)中,然后成为了该客户端状态的一部分。该模 式分离了客户端依赖本身行为的创建,这使得程序设计变得松耦合,并遵循了依赖反转和单一职责原则。与服务定位器 模式形成直接对比的是,它允许客户端了解客户端如何使用该系统找到依赖。
依赖注入产生的背景:传统应用程序通常是在类内部执行代码中主动创建这个类所依赖的其它对象, 从而 导致类与类之间发生紧密耦合,使得类难于测试和隔离,最终导致系统的扩展和维护异常困难。
依赖注入用来解决组件之间依赖关系、配置及生命周期管理, 通过转移对象控制权,可以解决类之间的耦合问题, 对象与对象之间是松散耦合关系,更重要的是使得应用程序体系结构变得非常灵活, 很好的体现了面向对象的设计法则之一—依赖设计原则
2.知识剖析
依赖注入的原理:程序运行过程中,如需另一个对象协作(调用它的方法、访问他的属性)时,无须在代码中创建被调用者,而是依赖于外部容器的注入, 调用者仅通过声明某个组件就可以获得组件的控制权,而对该组件的依赖关系管理、查找、加载由外部完成。
在Angular中,依赖注入可谓无孔不入。通常在两种场景下会使用到依赖注入:
1.工厂方法定义的组件(components):如directive,factory,filter,provider,controller等。这些工厂函数需要注册到某个模块上。controller比较特殊,它虽然也是一种组件,但是特别之处是它与某个DOM元素关联,因此可以注入 s c o p e s e r v i c e , 而 其 他 组 件 只 能 注 入 scope service,而其他组件只能注入 scopeservice,而其他组件只能注入rootScope service。所有的供应商都只被实例化一次,也就说他 们都是单例的,除了constant,所有的供应商都可以被装饰器(decorator)装饰,value就是一个简单的可注入的值, service是一个可注入的构造器,factory是一个可注入的方法,decorator可以修改或封装其他的供应商,当然除了constant ,provider是一个可配置的factory。
2.模块提供的run/config方法。
Angular在加载模块时经过两个阶段:config和run。传入config函数的方法会在当前模块加载时执行;传入run函数的方法会在所有模块加载结束后执行。因此,在config阶段即可配置多个provider,但是在config阶段,只有provider 可以注入,因此自定义的service无法注入到config中,config阶段是对service进行配置的而不是使用service本身。 p r o v i d e s e r v i c e 本 身 就 是 一 个 p r o v i d e r ( 对 于 A n g u l a r 应 用 来 讲 相 当 于 一 个 ′ 元 p r o v i d e r ′ ) , 在 模 块 加 载 时 会 调 用 provide service本身就是一个provider(对于Angular应用来讲相当于一个'元provider'),在模块加载时会调用 provideservice本身就是一个provider(对于Angular应用来讲相当于一个′元provider′),在模块加载时会调用provide 的provider方法定义一个新的provider。
3.常见问题
依赖注入有几种方法
如何使用这几种依赖注入的方法
4.解决方案
依赖注入有几种方法
依赖注解有三种方式,(数组标注、添加$inject属性、隐式声明)。 其中前两种在代码minify时不会被破坏,推荐使用第一种方式。 第三种方式,书写最为简单明了,但是不能对它直接进行minify,需要改写为前两种。
如何使用这几种依赖注入的方法
1、数组标注 someModule.controller(‘MyController’, [' s c o p e ′ , ′ g r e e t e r ′ , f u n c t i o n ( scope', 'greeter', function( scope′,′greeter′,function(scope, greeter) { }]);
js压缩混淆不会有影响,优先考虑用该方式为组件定义依赖。在代码中通过在第二个数组类型的参数中声明了’$scope’,'greeter’等依赖,数组最后一个元素为实际的构造方法,注意在构造方法的参数列表与其面的数组元素是一一对应的。
2、显式注入声明( i n j e c t 属 性 ) v a r M y C o n t r o l l e r = f u n c t i o n ( inject属性) var MyController = function( inject属性)varMyController=function(scope, greeter) { } MyController. i n j e c t = [ ′ inject = [' inject=[′scope’, ‘greeter’]; someModule.controller(‘MyController’, MyController);
AngularJS提供了显式的方法来明确定义一个函数在被调用时需要用到的依赖关系。通过这种方法声明依赖,即使在源代 码被压缩、参数名称发生改变的情况下依然能够正常工作。我们给我们的函数设置的参数名称分别是 s c o p e 和 g r e e t e r , 然 后 我 们 在 后 面 使 用 M y C o n t r o l l e r . scope和greeter, 然后我们在后面使用MyController. scope和greeter,然后我们在后面使用MyController.inject=[’$scope’,‘greeter’];显式的将我们需要的依赖注入到MyController函数中;
3、隐式声明依赖 someModule.controller(‘MyController’, function($scope, greeter) { });
最简单的声明依赖的方式就是让设构造方法的参数与依赖的名字一样。如果没有明确的声明,AngularJS会假定参数名称 就是依赖的名称。请注意,这个过程只适用于未经过压缩和混淆的代码,因为AngularJS需要原始未经压缩的参数列表 来进行解析当AngularJS实例化这个模块时,会查找greeter并自然而然地把对它的引用传递进去这里我们先看一个简单的依赖注入的例子。
5.编码实战
6.扩展思考
AngularJS中的依赖注入与不用依赖注入的其他框架相比,有何优点?
-
模板功能强大丰富,并且是声明式的,自带了丰富的Angular指令;
-
是一个比较完善的前端MVC框架,包含模板,数据双向绑定,路由,模块化,服务,过滤器,依赖注入等所有功能;
-
依赖注入简化了组件之间处理依赖的过程(即解决依赖)。没有依赖注入,就不得不以某种方式自己查找$scope,很可能 得使用全局变量。这虽然能够工作,但是不如AngularJS的依赖注入技术这么简单。
-
在开发中使用依赖注入的主要好处是AngularJS负责管理组件并在需要的时候提供给相应函数。依赖注入还能够为测试带 来好处,因为它允许你使用假的或者模拟的对象来代替真实的组件,从而让开发者专注于程序的特定部分。
7.参考文献
参考资料:http://www.html-js.com/article/1980
—— 理解AngularJS中的依赖注入
参考资料:https://blog.csdn.net/luo_xinran/article/details/52153830
—— AngularJS基础 之 依赖注入的几种方法
8.更多讨论
1.上面说的这些依赖组件的本质是什么?
答:factory,service以及value全部都是用来定义一个provider的简写,
它们提供了一种方式来定义一个provider而无需输入所有的复杂的代码。
2.factory和value等服务与provider都是提供服务,为什么还要使用provider?
答:provider允许我们进行一些配置。在前面我们已经提到过当你通过provider(或者其他简写方法)创建一个服务时,你实际上创建了一个新的provider,它将定义我们的服务如何被创建。这些provider可以被注入到config函数中,我们可以和它们进行一些交互。
3.factory和service的区别是什么?
答:factory是普通function,而service是一个构造器(constructor),
Angular在调用service时会用new关键字,而调用factory时只是调用普通的function,
所以factory可以返回任何东西,而service可以不返回.factory可以返回任何东西,
它实际上是一个只有$get方法的provider
今天的分享就到这里啦,欢迎大家点赞、转发、留言、拍砖~