TAT.tennylv AngularJs依赖注入的研究
In Web开发 on 2015年09月01日 by view: 2,747
6

什么是依赖注入呢,我的理解,简单点就是说我的东西我自己并不像来拿着,我想要我依赖的那个人来帮我拿着,当我需要的时候,他给我就行了。当然这只是简单的理解,还是用代码解释比较清楚一些。

这里有一个function,很简单。

我们调用它:

那么,就像我上面说的,我能不能自己不传参数呢,例如:

如何才能实现让别人帮我们注入这个参数呢:

像这样,我们在定义参数的时候这样传:

我们再调用a方法:

这其实就是最简单的依赖注入了,当然这么简单是不行的,其实这是很无意义的,下面我们来看一下高深的angularjs:

 

上面这段代码定义了angularjs的controller里面用到了scope,这样还看不出问题,在看下面:

上面这段代码在原来的基础上增加了http,那么问题就来了,angular在调用controller的时候怎么知道我需要scope还是http还是两个都需要呢,这就牵着到了angular里的依赖注入,那么我们来模拟一下。

假设没有angular的情况下,我们:

肯定会报错的,然后我们来修改下我们的inject:

这里解释一下,我们用了dependencies来存储所有的依赖,register来实现注册依赖,resolve方法来实现注入。

然后我们模仿angular来预先注册几个模块:

然后我们就可以注入了:

我们只需要http和scope,所以我们只传了两个,虽然这样看似解决了依赖注入,但是还有很多问题,比如我要交换两个参数的位置就不行了。

于是翻看了angularjs的源码,找到了:

我们忽略掉一些细节代码,只看我们需要的。annotate方法和我们的resolve方法很像。它转换传递过去的func为字符串,删除掉注释代码,然后抽取其中的参数。让我们看下它的执行结果,修改一下resolve方法:

打印出argDecl:

可以看到,这个数组拿到了func的参数,argDecl[1] = “$scope,$http”;

根据这个,我们来修改resolve:

OK,这次我们不用在意参数的顺序了,但是angular远比我们要想的多,大多数情况下,我们的js都是要压缩的,所以function的实参会被替换,如果是那样的话,我们这个方法的argDecl[1] = “$scope,$http”;就会是argDecl[1] = “r,t”;类似这样的变量,那么又该怎么解决呢?

angular官方有这样的解释:

为了克服压缩引起的问题,只要在控制器函数里面给$inject属性赋值一个依赖服务标识符的数组,就像:

那么,用到我们这个方法里面又该怎么实现呢?那我们在看看angular的源码吧:

看到了吧,之所以用到数组也是有原因的,把需要的依赖写在方法的前面,于是,应用到我们的reslove方法:

OK,到这里,便可以用我们的inject来模拟angular的依赖注入了,当然,真正angular的依赖注入还有很多东西,这里就不在详细描述了。

以上观点都是我的个人见解,如有错误欢迎指正!

 

参考资料:关于anjularjs双向绑定的研究

原创文章转载请注明:

转载自AlloyTeam:http://www.alloyteam.com/2015/09/angularjs-study-of-dependency-injection/

  1. jinglf 2017 年 1 月 13 日

    分析的挺好

  2. 呆呆的阿饭 2016 年 8 月 26 日

    今天面试被问到Angular依赖注入的实现原理,没答上,赶紧过来看看

  3. 换个昵称 2016 年 5 月 26 日

    初学angularjs,循序渐进,通俗易懂。

  4. 朕还能学啊 2016 年 5 月 4 日

    ( ̄▽ ̄)”初学angular

  5. 缚锥共80 2015 年 10 月 29 日

    [悲伤]

  6. 刘文俊 2015 年 10 月 6 日

    也看过angular依赖注入的源码,不过你这种循序渐进的讲解更能让人明白它的实现思路。

发表评论