AngularJS单页应用运行时覆盖自定义directive指令的实现方案咨询
需求可以实现,以下是具体的原因说明和解决方案:
问题原因
AngularJS默认允许注册多个同名指令,所有注册的指令会按顺序存入数组,默认优先级相同的情况下会依次执行。但你的两个指令都声明了隔离scope,同一个元素上只能有一个隔离scope生效,因此只有首次注册的指令会正常运行,后续注册的会被静默忽略。同时你当前的decorator逻辑没有生效,是因为你未在decorator中移除旧指令,且没有清理AngularJS内置的指令缓存。
可行的解决方案
这里提供两种可直接落地的实现方式:
方案1:手动清理旧指令缓存后注册新指令
在第二页JS代码的最前面添加清理逻辑,清除旧的指令注册记录和缓存后再注册新指令:
// 第二页JS开头添加 appGML.run(function($compile) { // 清除AngularJS内置的指令缓存 delete $compile._directiveCache.singleSelectKeyUp; // 移除invokeQueue中旧的同名指令注册记录 appGML._invokeQueue = appGML._invokeQueue.filter(item => { return !(item[0] === '$compileProvider' && item[1] === 'directive' && item[2][0] === 'singleSelectKeyUp'); }); }); // 后面接你原来的singleSelectKeyUp指令注册代码 appGML.directive('singleSelectKeyUp', function ($resource, $compile, $parse, $timeout, $http, $document,$q) { return { restrict: 'A', require: 'ngModel', link: function (scope, element, attr, ngModel) { return scope.$watch(function () { return ngModel.$modelValue; }, function (name) { console.log('second page'); }); } }; });
方案2:通过decorator过滤指令数组
调整你路由配置中的decorator逻辑,直接保留最后注册的新指令,移除旧指令:
// 把你原来loader中的decorator替换为以下逻辑,注意要放在脚本加载完成的回调中 $q.all(map).then(function (r) { $provide.decorator('singleSelectKeyUpDirective', ['$delegate', function ($delegate) { // 只保留最后注册的指令,移除之前的所有旧版本 return [$delegate.pop()]; }]); deferred.resolve(); });
验证效果
修改完成后依次加载两个页面,控制台会依次输出:
first page second page
符合预期要求。
内容的提问来源于stack exchange,提问作者Angularjsguy
相关产品推荐
相关产品推荐

