我将简单的分页从控制器转移到指令,并遇到了一个奇怪的问题。每次我从指令中更新父作用域时,它只会在下一次更改时更新。因此,如果ng-options是[10,20,30]并且我将其更改为10 - 没有任何反应。然后我将其更改为20并更新为之前的值10,接下来更改为模型更新为我之前选择的值的任何值,依此类推
我尝试使用$ scope。$ apply但它没有帮助。我仍然得到延迟更新。我错过了什么?我意识到它与摘要更新和$ scope有关。$ apply但我无法弄清楚在哪里使用它。我尝试的任何东西都不起作用。
相关控制器部分:
vm.pages = 0;
vm.articles = [];
vm.load = { page: { batch: 10, current: 1 }
, sort: { _id: -1 }
, filter: {}
};
vm.getArticles = function() {
articleS.list(vm.load, function (data){
vm.pages = data.pages;
vm.articles = data.articles;
});
}
指令:
.directive("paging", function() {
var scope = { update: '&', current: '=', pages: '=', batch: '=' };
function link(s, e, a) {
s.options = [10,20,50,100];
s.toPage = function(p) {
switch(p) {
case "last":
if (s.current != s.pages) {
s.current = s.pages;
s.update();
}
break;
case "next":
if (s.current < s.pages) {
s.current ++;
s.update();
}
break;
case "prev":
if (s.current > 1) {
s.current --;
s.update();
}
break;
default:
s.current = 1;
s.update();
}
}
}
return {
replace: true,
scope: scope,
templateUrl: 'paging.tpl',
link: link
}
});
指令模板:
<section class='pages'>
<select
ng-model="batch"
ng-change="toPage('first')"
ng-options="value for value in options">
</select>
<div>
<button ng-click="toPage('first')"> 1 </button>
<button ng-click="toPage('prev')"> << </button>
<div>{{current}}</div>
<button ng-click="toPage('next')"> >> </button>
<button ng-click="toPage('last')"> {{pages}} </button>
</div>
</section>
指令电话:
<paging
update="vm.getArticles()"
current="vm.load.page.current"
batch="vm.load.page.batch"
pages="vm.pages">
</paging>
答案 0 :(得分:6)
行。我想通了。
如果我理解正确的话,$ apply会在绑定到其父级的孤立范围变量上运行它时产生already in progress
错误。我认为'='会触发$ digest(这只是试图解决这个问题时的试验和错误的观察结果)。
我的问题是s.update()
函数在下一个摘要周期之前运行。因此局部范围变量“没有时间”复制到父范围。这就是为什么我只能在下一次操作或下一个消化周期中看到更新母鸡总是看到之前的变化。
与setTimeout(function(){ s.update() }, 2000)
一起玩证明了这一点。
如果我延迟执行几秒钟,那么我会看到更新正确的更改。延迟不是解决方案,减慢应用程序是非常愚蠢的。
然后我找到了角度$timeout(function() {})
这允许跳过延迟参数,该参数默认为0并且实际上没有延迟任何内容,但它确实确保回调在下一个摘要周期运行,以便可以将本地范围变量更新为父级。
if (s.current < s.pages) {
s.current ++;
$timeout(function() {
s.update();
});
}