ng-if环境下AngularJS表单无法被控制器访问的解决方案咨询
这个问题我之前也碰到过!确实是ng-if创建的子作用域在搞鬼——ng-if会生成一个独立的子作用域,而表单的引用默认是绑定在当前子作用域上的,你控制器所在的父作用域自然拿不到这个引用,所以才一直显示undefined。结合你提到的showChild控制外层子视图、isShown切换两个子视图的场景,给你几个靠谱的解决方案:
方法1:使用对象属性绑定(最推荐)
AngularJS的作用域是原型继承的,如果直接在作用域上定义基本类型变量,子作用域会创建一个同名的“遮蔽”属性,导致父作用域访问不到子作用域的变量。但如果用对象来存放表单引用,就能避免这个问题——因为子作用域会继承父作用域的对象引用,修改对象的属性会直接反映到父作用域中。
控制器代码:
app.controller('YourController', function() { var vm = this; // 控制外层子视图的显示 vm.showChild = false; // 控制child-view-1和child-view-2的切换 vm.isShown = true; // 用一个对象来存放表单引用 vm.formContainer = {}; });
HTML代码:
<div ng-controller="YourController as vm"> <button ng-click="vm.showChild = !vm.showChild">切换外层子视图</button> <button ng-click="vm.isShown = !vm.isShown">切换子视图1/2</button> <div ng-if="vm.showChild"> <div ng-if="vm.isShown">child-view-1</div> <div ng-if="!vm.isShown"> <!-- 把表单绑定到vm.formContainer的属性上 --> <form name="vm.formContainer.childForm"> <!-- 表单控件 --> <input type="text" ng-model="vm.formData.username"> </form> </div> </div> </div>
这样你在控制器里就能通过vm.formContainer.childForm随时访问到这个表单,不管ng-if怎么切换,都不会出现undefined的情况。而且用controllerAs语法还能避免作用域混淆,代码可读性更高。
方法2:改用ng-show(适合不需要销毁DOM的场景)
如果你的业务场景不需要销毁DOM来节省资源,可以把ng-if换成ng-show——ng-show只是通过CSS隐藏元素,不会创建新的子作用域,表单的引用会直接绑定到父作用域上,控制器自然能直接访问。
示例:
<div ng-show="vm.showChild"> <div ng-show="vm.isShown">child-view-1</div> <div ng-show="!vm.isShown"> <form name="vm.childForm"> <!-- 表单内容 --> </form> </div> </div>
不过这种方法的局限性是DOM一直存在,如果你有大量复杂控件,可能会影响性能,所以还是方法1更通用。
方法3:使用$parent直接访问父作用域(不推荐)
你也可以通过$parent直接让表单绑定到父作用域上,但这种方法耦合性很高,一旦你的DOM结构发生变化(比如嵌套层数改变),代码就会失效,所以不推荐在实际项目中使用。
示例:
<div ng-if="!vm.isShown"> <form name="$parent.childForm"> <!-- 表单内容 --> </form> </div>
控制器里通过$scope.childForm就能访问,但还是尽量用方法1来保证代码的健壮性。
内容的提问来源于stack exchange,提问作者user3681549

