为了掌握AngularJS,我决定玩一个例子,特别是简单地添加一个"完整的"屏幕显示Todo示例,当用户输入5个待办事项时,它使用一个开关盒切换到另一个div。如果有任何用途,可在此处http://jsfiddle.net/FWCHU/1/使用代码。
但是,似乎每个switch-case都有自己的范围($ scope.todoText不可用),但是可以使用"这个"来访问它。在这种情况下,从addTodo()内部。到目前为止一切都那么好,但是我想要在switch-case之外访问todoText(在switch-case里面),我该怎么做呢?我是否可以将switch-case范围绑定到模型,是否可以通过其他方式访问,还是应该以其他方式解决?
PS。我不试图找到上述代码的任何解决方案,我很确定我知道如何在不使用switch-case的情况下解决它,我想了解范围如何工作这个案子!
答案 0 :(得分:7)
我不确定如何直接访问内部作用域,但这是通过绑定到对象而不是基元来访问外部作用域中相同文本的一种方法。
1)将todoText
声明为对象而不是控制器中的基元:
$scope.todoText = {text: ''};
2)绑定到todoText.text
而不是todoText
:
<form ng-submit="addTodo()">
<input type="text" ng-model="todoText.text" size="30" placeholder="add new todo here">
<input class="btn-primary" type="submit" value="add">
</form>
3)修改现有功能以使用todoText.text
:
$scope.addTodo = function() {
$scope.todos.push({text:$scope.todoText.text, done:false, width: Math.floor(Math.random() * 100) + 50});
$scope.todoText.text = '';
};
请查看this fiddle,并注意当您输入内容时文本框下方显示的文字是访问外部范围内的todoText.text
。
如果您更改代码以使用原语(例如this fiddle),则父范围todoText
将不会反映您对文本框所做的任何更改。这可能更多地与JavaScript如何复制引用值有关(请参阅this post了解更多信息)而不是AngularJS特定的事情。
答案 1 :(得分:5)
Update2:现在我对AngularJS有了更多了解,这里有一个更好的答案。
说我想访问todoText(在switch-case中) 在开关盒之外,我该怎么做呢?
父作用域无法访问子作用域。 (这种限制的一个原因,according to Angular developers,是为了更容易对范围进行内存管理。)(好吧,你可以使用$$ childHead和$$ childTail来访问子范围,但你不应该!)
我是否可以将switch-case范围绑定到模型,是吧 可以通过其他方式获得,或者应该在其他方面解决 方式是什么?
从子范围访问父模型有三种常用方法:
要将您的小提琴转换为使用$ parent:
<input type="text" ng-model="$parent.todoText" ...
$scope.addTodo = function() {
$scope.todos.push({text: $scope.todoText, ...
$scope.todoText = '';
正如我在Gloopy的回答中提到的那样,ng-repeat和ng-switch都有新的子范围原型继承父范围。 ng-repeat还将循环变量/项复制到新的子范围(以及@Gloopy描述的原语与对象的细微差别)。 ng-switch不会复制父作用域中的任何内容。
要查看内部/子范围的外观,请在ng-switch-when之后添加以下内容:
<a ng-click="showScope($event)">show scope</a>
并将其添加到您的控制器:
$scope.showScope = function(e) {
console.log(angular.element(e.srcElement).scope());
}
Update1:(为了清晰起见,删除了添加了错误的建议,[];
对于这种情况,AngularJS正在创建额外的内部作用域(隐式),而你真的不需要/需要另一个控制器,我喜欢Gloopy的解决方案。一项服务(我最初在下面提出的建议)是[这样做的错误方法] 这里可能有点过分。我也喜欢Gloopy的解决方案不需要在控制器方法中使用'this'。
原始答案 :(为了清晰起见,删除了添加了错误建议,[]为了清晰起见)
要查看范围的创建位置(如果您还没有尝试过,那么它很方便):
.ng-scope { margin: 4px; border: 1px dashed red }
要在switch-case之外访问todoText(因此在其范围之外),你实际上是在询问控制器之间的通信,因为涉及多个范围。您有几个选择,但服务可能是最好的。将数据(需要共享)存储在服务中,并将该服务注入需要访问数据的每个控制器。
对于您的具体示例,我认为您需要将控制器附加到每个交换机案例并将服务注入其中,以便访问共享数据。
另见AngularJS: How can I pass variables between controllers?。
其他选择:
在内部作用域中使用$ scope。$ parent是[实现此目的的一种方法 - 请参阅上面的Update2] 不推荐,因为那时控制器会假设数据的呈现方式。
建议不要使用$ rootScope,除非是简单的一次性应用程序。共享数据可能会开始具有自己的生命,并且$ rootScope不是发生这种情况的地方。服务更容易重用,添加行为等。
使用$ scope。$ emit是另一种选择,但它似乎很乱并且有点奇怪:发出事件来共享数据(而不是触发行为)。
[在父范围内使用对象可能是最好的 - 请参阅@ Gloopy的答案。]