Angular表单选项切换控制div显示隐藏异常问题求助
解决嵌套div切换显示/隐藏的AngularJS作用域问题
嘿,我太懂你这个头疼的问题了!在嵌套控制器里切换状态时,外层的div死活不跟着变化对吧?其实根源是AngularJS的作用域继承机制在搞鬼。
问题分析
你原来的代码里,父控制器MainCtrl定义了一个布尔类型的toggle变量,然后在子控制器InnerCtrl里尝试修改它。但AngularJS的子作用域对原始类型(字符串、数字、布尔值)会创建一个本地副本,而不是直接修改父作用域的变量。这就导致你在子控制器里改的toggle只是子作用域自己的,父作用域里控制显示隐藏的那个toggle完全没变化,自然另一个div不会隐藏。
解决方案:用对象属性代替原始类型变量
最靠谱的解决办法是把要绑定的变量放到一个对象里,因为对象在作用域继承中是引用传递的,子作用域修改对象的属性会直接同步到父作用域。
修改后的控制器代码:
var app = angular.module('plunker', []); app.controller('MainCtrl', function($scope) { // 把toggle包装在一个对象里 $scope.viewState = { toggle: false }; }); app.controller('InnerCtrl', function($scope) { $scope.switchDiv = function() { // 修改对象的属性,会直接影响父作用域的viewState $scope.viewState.toggle = !$scope.viewState.toggle; }; });
对应的模板代码:
<div ng-controller="MainCtrl"> <!-- 用viewState.toggle判断显示隐藏 --> <div ng-show="!viewState.toggle"> <div ng-controller="InnerCtrl"> <button ng-click="switchDiv()">切换到另一个div</button> </div> </div> <div ng-show="viewState.toggle"> 这是要显示的另一个div <button ng-click="viewState.toggle = false">切换回去</button> </div> </div>
为什么这个方法有效?
AngularJS的作用域继承基于JavaScript原型链。当你访问子作用域的viewState时,因为子作用域没有这个对象,会向上查找父作用域的viewState,然后修改它的toggle属性——这个修改会直接作用在父作用域的对象上,所以外层的ng-show能实时感知到变化,正确切换div的显示/隐藏。
不推荐的方案:用$parent
虽然你可以在子控制器里直接用$parent.toggle来修改父作用域的变量,但这种写法耦合性太高,一旦控制器嵌套结构变化,代码就会出错,所以不建议使用。
内容的提问来源于stack exchange,提问作者Karthey Sundarem




