AngularJS嵌套ng-repeat下form-template共用模型值的实现方法
这个问题在AngularJS的嵌套ng-repeat场景里太常见了——每个ng-repeat都会创建自己的子作用域,嵌套之后内层作用域的变量查找会沿着作用链往上走,但如果我们想让模板稳定使用外层的trackerWidgetData而不受内层dependWidgetData的干扰,有几个靠谱的方案:
1. 最推荐:使用控制器别名(Controller As)模式
这是AngularJS官方推荐的写法,从根源上避免作用域继承的混乱。把你的控制器绑定到一个别名上,比如vm(ViewModel的缩写),然后模板里所有需要访问外层模型的地方都用vm.trackerWidgetData,不管嵌套多少层,它都会直接指向控制器实例上的变量,不会被子作用域覆盖。
示例代码:
<!-- 外层控制器绑定别名 --> <div ng-controller="TrackerController as vm"> <!-- 外层ng-repeat --> <div class="listview-trckr-new clearf" ng-repeat="tracker in vm.trackerWidgetData"> <!-- 嵌套ng-repeat,使用内层变量dependWidgetData --> <div ng-repeat="depend in vm.dependWidgetData"> <!-- 引入form-template,模板里直接用vm.trackerWidgetData --> <ng-include src="'form-template.html'"></ng-include> </div> </div> </div>
你的form-template里直接写:
<!-- form-template.html --> <input type="text" ng-model="vm.trackerWidgetData.someProperty">
2. 灵活可控:用指令封装模板(隔离作用域)
如果你的form-template需要频繁复用,把它封装成一个带隔离作用域的指令是更规范的做法。隔离作用域可以明确接收外部传递的模型,完全避免作用链查找的问题。
首先定义指令:
angular.module('yourApp').directive('formTemplate', function() { return { restrict: 'E', scope: { // 双向绑定外部传入的模型 widgetModel: '=' }, templateUrl: 'form-template.html' }; });
然后在嵌套ng-repeat中使用:
<div ng-repeat="tracker in trackerWidgetData"> <div ng-repeat="depend in dependWidgetData"> <!-- 明确传递外层的tracker作为模型 --> <form-template widget-model="tracker"></form-template> </div> </div>
模板里直接使用指令隔离作用域里的变量:
<!-- form-template.html --> <input type="text" ng-model="widgetModel.someProperty">
3. 快速临时方案:用ng-init传递变量
如果不想改太多代码,也可以在引入模板的时候,用ng-init把外层的trackerWidgetData(或者当前外层循环的item)传递给模板内部的一个变量,模板里直接用这个变量即可。
示例:
<div ng-repeat="tracker in trackerWidgetData"> <div ng-repeat="depend in dependWidgetData"> <!-- 把外层的tracker传递给模板里的formModel变量 --> <ng-include src="'form-template.html'" ng-init="formModel = tracker"></ng-include> </div> </div>
模板里替换成:
<input type="text" ng-model="formModel.someProperty">
不推荐:用$parent访问父作用域
虽然可以用$parent.trackerWidgetData在模板里直接访问父作用域的变量,但如果是多层嵌套,你需要写$parent.$parent.trackerWidgetData,这种写法非常脆弱——只要嵌套层级变了,代码就会失效,维护性极差,所以尽量避免。
内容的提问来源于stack exchange,提问作者Manish Balodia

