学习一种语言,不仅仅只会用,更多的是对一种语言的好奇,总有想知道原理的决心。让angularjs有哪些好奇点呢?
1.注入器(Injector)
2.模块(Module)
3.服务(Serivce或Provider)
4.作用域(Scope)
5.双向绑定(Tow way binding)
问题:
1.函数的DI是什么时间产生的?
在使用他的场景中,一般为:module中的config,module中的run,$ControllerProvider触发
2.双向绑定是通过scope的$watch和$digest实现的,那系统是什么时间调用$digest这个函数的呢?
(所有的可输入控件和事件都会去调用$apply,而$apply间接调用$digest)。
那在控制器或service改变$scope时,是什么时间去调用$digest?
由于控制器和service都是由系统启动的,因此在调用bootstrap时,最后会通过以下代码统一调用一次$apply
injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', '$animate', function (scope, element, compile, injector, animate) { scope.$apply(function () { element.data('$injector', injector); compile(element)(scope); }); }] );
3.作用域是怎么产生的,如何为指令的链接分配作用域的?
作用域是在链接时产生,系统上从HTML的最外层一直向里层连接,如果遇到需要创建scope的地方,就创建,否则原用父层的scope
$node = jqLite(node); if (nodeLinkFn) { if (nodeLinkFn.scope) { childScope = scope.$new(); $node.data('$scope', childScope); } else { childScope = scope; } childTranscludeFn = nodeLinkFn.transclude; if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) { nodeLinkFn(childLinkFn, childScope, node, $rootElement, createBoundTranscludeFn(scope, childTranscludeFn || transcludeFn) ); } else { nodeLinkFn(childLinkFn, childScope, node, $rootElement, boundTranscludeFn); } } else if (childLinkFn) { childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn); }以上是compositeLinkFn的一部分,而其中的childLinkFn为孩子的compositeLinkFn,nodeLinkFn中会调用childLinkFn,因此这些函数会不停的调下去,直到nodeLinkFn和childLinkFn都为空。
nodeLinkFn这个函数共做3个步骤
A.调用指令的预处理连接(指令compile函数返回时,返回含pre连接函数的对象)
B.调用childLinkFn
C.调用指令的后处理连接(指令中提供的compile和link)
4.为何作用域中变量会有继承关系?
在链接中,会产生两种作用域,一种为独立的,一种是由父亲产生的儿子作用域是继承(采用原型链的机制)
if (isolate) { child = new Scope(); child.$root = this.$root; // ensure that there is just one async queue per $rootScope and its children child.$$asyncQueue = this.$$asyncQueue; child.$$postDigestQueue = this.$$postDigestQueue; } else { ChildScope = function () { }; // should be anonymous; This is so that when the minifier munges // the name it does not become random set of chars. This will then show up as class // name in the web inspector. ChildScope.prototype = this; child = new ChildScope(); child.$id = nextUid(); }