AngularJS 多指令Scope问题的解决(2)

// HTML字符串 var html = '<div ng-bind="exp"></div>'; // 将HTML字符串转换为DOM模板 var template = angular.element(html); // 编译DOM模板返回link函数 var linkFn = $compile(template); // 将编译后的模板与scope链接 var element = linkFn(scope); // 添加到DOM中 parent.appendChild(element);

分析

compile只在编译时执行一次,只要页面中存在一个该指令,该指令的link方法就执行一次。

所以,AngularJS使用$compile编译我的指令,然后看我页面中用到了三个该指令,并且都是独立scope,所以就创建了三个scope。

然后使用这三个scope去调用link函数。

前面已经提到,AngularJS会将link函数统一组合成一个“组合的”link函数,所以我们可以猜想,组合函数中的link函数的数量与指令的数量一致,所以三次调用的是一个link函数,link函数只有一个实例!

linkFn(scope)

将scope传进去作为link函数的入参。

上面的事件监听都是没毛病的,将传入的scope绑定到视图,然后添加到DOM中,然后就与这个link函数无关了。

AngularJS 多指令Scope问题的解决

但是这个filter就不行了。

第一个scope调用,filter功能是过滤第一个scope的accuracyList,第二个scope调用,filter功能是过滤第二个scope的accuracyList。

所以第三次执行时,第三个scope将之前的两个都覆盖了,link函数中的filter的作用变成了过滤最后一个scope的accuracyList。

AngularJS 多指令Scope问题的解决

<!-- 不确定度 --> <ui-select ng-model="selected" theme="bootstrap" ng-change="updateModel(selected)"> <ui-select-match placeholder="请选择"> {{ $select.selected._value }} </ui-select-match> <ui-select-choices repeat="accuracy in accuracyList"> <div ng-bind-html="accuracy._value"></div> </ui-select-choices> </ui-select>

所以这里下拉框显示的是不确定度过滤后的_value的值,这里的空字符串看起来不明显,加上test测试一下。

AngularJS 多指令Scope问题的解决

所以,这块视图绑定的scope是正确的,只是时间监听之后去过滤数据,因为过滤的并不是当前scope的数据,所以accuracy._value就没有值,是undefined,所以显示一个空的字符串。

AngularJS 多指令Scope问题的解决

解决方案

明白了原理之后解决问题自然易如反掌,只需将filter与scope独立即可,这样就不受每次执行不同scope的影响了。

AngularJS 多指令Scope问题的解决

总结

很多东西,书上是没有的,需要我们自己去发现,去分析,去解决。

翻开了之前遇到指令编译问题时从别人博客里学习来的手动编译方法。

angular.module('webappApp') .directive('reCompile', function($compile) { return { restrict: 'A', link: function postLink(scope, element, attrs) { // 监听使用该指令的元素上的ngBindHtml attrs.$observe('ngBindHtml', function() { // 如果元素使用了ngBindHtml指令 if (attrs.ngBindHtml) { // 重新编译 $compile(element[0].children)(scope); } }); } }; });

记得之前的需求是,数据经过过滤器过滤,返回的是一段HTML代码,虽然使用ng-bind-html能将该段代码添加到DOM中,但是这段代码中有指令,因为该指令不是初始时就有的,所以,这个指令是不会被编译的。

所以需要编写一个重新编译的指令,手动编译动态创建的指令。

记得当时,看这段代码也不是那么完全理解,现在学习完指令的编译之后,再去翻看之前的代码,一切原来是如此简单。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/6c827b4adb4c72895d7522f82bca79b5.html