AngularJS:切换ng-if渲染区块时如何置空对应$scope变量
ng-change!AngularJS原生清空未渲染字段的方案 嘿,这个需求我之前在项目里碰到过,刚好知道几个完全基于AngularJS原生特性的解法,不用写额外的ng-change逻辑就能自动清空未渲染区块的变量,完美符合你的要求!
首先得纠正一个常见的小坑:如果你的$scope变量是a、b这类原始类型,ng-if创建的子作用域会生成它们的副本,直接修改的话不会同步到父作用域。所以第一步,我们把变量改成对象属性,这样子作用域会继承对象的引用,修改的是同一个数据源。
比如在控制器里定义:
$scope.formData = { yesFields: { a: '', b: '', c: '' }, noFields: { x: '', y: '', z: '' }, choice: 'yes' };
接下来分两种情况,根据你的AngularJS版本来选:
方案一:AngularJS 1.5+ 用原生ng-on-destroy
从1.5版本开始,AngularJS提供了ng-on-destroy指令,它会在元素被销毁时触发对应的表达式。我们刚好可以用这个特性,在ng-if区块被销毁时清空另一组的变量:
<!-- 单选按钮组 --> <label> <input type="radio" ng-model="formData.choice" value="yes"> Yes </label> <label> <input type="radio" ng-model="formData.choice" value="no"> No </label> <!-- Yes对应的输入框组,销毁时清空No组的变量 --> <div ng-if="formData.choice === 'yes'" ng-on-destroy="formData.noFields = {x: null, y: null, z: null}"> <input type="text" ng-model="formData.yesFields.a" placeholder="Input A"> <input type="text" ng-model="formData.yesFields.b" placeholder="Input B"> <input type="text" ng-model="formData.yesFields.c" placeholder="Input C"> </div> <!-- No对应的输入框组,销毁时清空Yes组的变量 --> <div ng-if="formData.choice === 'no'" ng-on-destroy="formData.yesFields = {a: null, b: null, c: null}"> <input type="text" ng-model="formData.noFields.x" placeholder="Input X"> <input type="text" ng-model="formData.noFields.y" placeholder="Input Y"> <input type="text" ng-model="formData.noFields.z" placeholder="Input Z"> </div>
这个方案完全是原生的,不需要额外写控制器逻辑,逻辑和视图绑定在一起,非常符合AngularJS的MVVM思路。当用户切换单选按钮时,原来的区块被销毁,触发ng-on-destroy里的表达式,自动把另一组变量设为null。
方案二:AngularJS 1.5以下 自定义监听$destroy的指令
如果你的项目还在使用1.5以下的版本,没有ng-on-destroy,可以写一个超简单的自定义指令来监听元素的$destroy事件:
angular.module('yourAppName').directive('clearOnDestroy', function() { return { scope: { clearOnDestroy: '=' }, link: function(scope, element) { // 监听元素销毁事件 element.on('$destroy', function() { // 遍历目标对象,把所有属性设为null angular.forEach(scope.clearOnDestroy, function(val, key) { scope.clearOnDestroy[key] = null; }); }); } }; });
然后在视图里用这个指令替代ng-on-destroy:
<div ng-if="formData.choice === 'yes'" clear-on-destroy="formData.noFields"> <!-- Yes组输入框 --> </div> <div ng-if="formData.choice === 'no'" clear-on-destroy="formData.yesFields"> <!-- No组输入框 --> </div>
这个指令复用性很强,以后其他地方需要类似的逻辑也可以直接用。
为什么要用对象属性绑定?
这里再强调一下:如果直接绑定$scope.a、$scope.x这类原始类型变量,ng-if创建的子作用域会复制这些变量,导致你在子作用域里修改的是副本,父作用域的变量不会被正确清空。用对象属性的话,子作用域继承的是对象的引用,修改的是同一个对象的属性,所以能正确同步到父作用域。
总结一下,这两个方案都是完全基于AngularJS原生特性的,不需要写ng-change逻辑,代码简洁且符合框架设计思想,完美解决你的问题!
内容的提问来源于stack exchange,提问作者Priyesh Parikh

