我是Angular的新手,但真的很喜欢它的方法。我有一个HTML文件,我在ng-init
元素中使用<div>
初始化变量,其中我还声明了一个带有ng-controller
指令的控制器:
<div ng-controller="myCtrl" ng-init='foo="bar"'>
如果我console.log
来自控制器脚本的$scope
对象,我可以看到其他列出的foo
属性,但是当我尝试从同一个脚本访问它时,它给了我undefined
。我也在使用Batarang,它向我展示了<div>
范围内的模型,该模型还包含foo
属性。
我从Pass variables to AngularJS controller, best practice?的第二个答案中知道我可以通过将ng-init
指令移到外部<div>
来解决问题,但我想知道实际发生了什么在幕后。任何帮助都非常感谢,提前感谢。
div
元素中指令的顺序无关紧要。即使在ng-init
ng-controller
,问题仍然存在
答案 0 :(得分:18)
ng-init
在外部/内部els中的不同行为。编译包括不同的步骤。在这种情况下最相关的是:
以每个DOM节点为基础以此顺序发生(即对于每个节点,控制器代码,如果存在,则在任何预链接,链接或后链接f之前执行)
ng-init
在指定的节点上注册pre
- 链接f,$eval
指令的内容(在我的示例中,f为{{{{{{ 1}} prop)。因此,当执行同一节点的控制器代码时,支柱尚不存在,这符合@ Aron的答案
在编译阶段,Angular在深度优先的基础上从根向下遍历DOM,这意味着父级在子级之前编译。将foo
指令放在外部el中允许子节点的控制器继承外部的作用域。这解释了'外部'黑客
ng-init
时,回调f可以找到它
我建议基于异步JS和Angular特性的其他两个可能的hacks(参见this jsFiddle)。一个涉及使用$eval
JS本地f,而另一个涉及更多'Angular'并转向setTimeout
$evalAsync
指令的实现存在缺陷。我已经破解了Angular的代码来试验各种各样的实现。这并不困难(即使在删除ng-init
指令本机代码之前添加了2行代码),并且在应用于上面的jsFiddle中的代码时也能正常工作,但我还没有在复杂的应用程序上测试它。对于那些感兴趣的人,这是我正在做的事情(参考文献v 1.2.0-rc2):
ng-init
f块中的applyDirectivesToNode
局部变量nodeHasInitData
var分配了directiveName
prop值之后,我将对directive.name
静态字符串进行测试,该字符串是Angular分配给它的规范化名称。在节点上声明它时的"ngInit"
指令ng-init
设置为nodeHasInitData
。如果测试失败,则无法完成任务( - true
在关闭中仍然是nodeHasInitData
undefined
f块中,在nodeLinkFn
块之前检查节点中是否存在控制器(上面列表中的步骤1),我正在添加一个关于值的测试if
(我可以这样做,因为nodeHasInitData
内已定义nodeLinkFn
applyDirectivesToNode
,这是本地scope.$eval(attrs.ngInit)
指令的预链接f。 ng-init
和scope
都是attrs
的原始参数,因此它们可用。如果测试失败,则无法完成任务 <子>
1.实际上,我已经复制了它,因为nodeLinkFn
指令定义的预链接f仍然存在。然而,这并不是很重要,我认为通过更改/删除指令对象可以轻松避免
为了避免复制,出于上述黑客的说明目的,将ng-init
Angular var的赋值代码替换为ngInitDirective
答案 1 :(得分:2)
首先创建控制器,然后设置foo = bar。
这意味着在你的控制器的代码中,foo还没有存在。但是在调试时,它已经被创建了。
这是一种解决方法,但我认为这真的是一个黑客。 Why is the variable set in ng-init undefined in $scope in AngularJS?
imho修复此问题的角度方法不是将数据放入视图中。数据属于您的模型或控制器或服务。这是为了使关注点分离有效
答案 2 :(得分:1)
解决方法是使用ng-init的函数。
<div ng-app>
<div ng-controller="MyCtrl" ng-init="init('kittens')">
Page title is {{ pageTitle }}
</div>
</div>
控制器:
var MyCtrl = function($scope) {
$scope.init = function(pageTitle) {
$scope.pageTitle = pageTitle;
}
};
我一直在使用ng-init为我的控制器指定一个类型 - 即控制器在应用程序中多次使用,但每次需要一条不同的信息。它节省了我为每种类型制作一个单独的控制器。
相关问题:
Why is the variable set in ng-init undefined in $scope in AngularJS?