第二个 Angular 指令首先遇到 $timeout
Second Angular directive suffers from $timeout in first
在构建一个简单的 Angular 应用程序时,我使用了两个指令。
第一个指令创建幻灯片,第二个指令服务一些阅读更多 links.
app.directive('slider', function($timeout) {
return {
restrict: 'AE',
replace: true,
scope: {
images: '='
},
link: function(scope, elem, attrs) {
var timer;
scope.currentIndex = 0; // Initially the index is at the first image
scope.next = function() {
scope.currentIndex < scope.images.length - 1 ? scope.currentIndex++ : scope.currentIndex = 0;
};
scope.prev = function() {
scope.currentIndex > 0 ? scope.currentIndex-- : scope.currentIndex = scope.images.length - 1;
};
var sliderFunc = function() {
timer = $timeout(function() {
scope.next();
timer = $timeout(sliderFunc, 5000);
}, 10);
};
sliderFunc();
scope.$watch('currentIndex', function() {
scope.images.forEach(function(image) {
image.visible = false; // make every image invisible
});
if (scope.images.length > 0) {
scope.images[scope.currentIndex].visible = true; // make the current image visible
}
});
scope.$on('$destroy', function() {
$timeout.cancel(timer); // when the scope is getting destroyed, cancel the timer
});
},
templateUrl: 'app/slider.tpl.html'
};
})
.directive('readMore', function() {
return {
restrict: 'A',
scope: true,
link: function(scope, elem, attrs) {
scope.more = false;
elem.find('.readmore').bind('click', function() {
scope.more = scope.more === false ? true : false;
});
}
};
});
两个指令都按预期工作。
第一个指令使用 $timeout,因此幻灯片图像每 5 秒循环一次。
阅读更多 link 中存在问题。
当我单击 link 时,脚本(指令)等待(最多)5 秒。执行,同时幻灯片也执行。
我是 Angular 的新手,但我认为具有不同范围的指令不会相互干扰。
我该怎么做才能让阅读更多 links 立即触发?
发生这种情况是因为在第二个指令中,您正在 jQuery 单击事件中更新范围,该事件超出了 Angular 生命周期。
视图将在下一个摘要周期刷新,例如由任何 $timeout
调用触发。
一个快速而肮脏的解决方法是在你的点击侦听器中调用第二个指令的 scope.$apply()
(或 scope.$digest()
)。
更好的解决方法是使用 ng-click
指令而不是 jQuery 侦听器以 angular 方式捕获点击事件(然后让它们成为其生命周期的一部分 -无需手动 $apply)
更新: 这里是如何使用ng-click
:
<a class="readmore" ng-click="more = !more">Read more</a>
作为旁注,您可能应该使用 $interval
而不是 $timeout
因为它是您实际模拟的内容。
您在 angular 上下文之外修改 scope.more。请在那里调用 scope.$digest()
elem.find('.readmore').bind('click', function() {
scope.more = scope.more === false ? true : false;
scope.$digest();
});
在构建一个简单的 Angular 应用程序时,我使用了两个指令。 第一个指令创建幻灯片,第二个指令服务一些阅读更多 links.
app.directive('slider', function($timeout) {
return {
restrict: 'AE',
replace: true,
scope: {
images: '='
},
link: function(scope, elem, attrs) {
var timer;
scope.currentIndex = 0; // Initially the index is at the first image
scope.next = function() {
scope.currentIndex < scope.images.length - 1 ? scope.currentIndex++ : scope.currentIndex = 0;
};
scope.prev = function() {
scope.currentIndex > 0 ? scope.currentIndex-- : scope.currentIndex = scope.images.length - 1;
};
var sliderFunc = function() {
timer = $timeout(function() {
scope.next();
timer = $timeout(sliderFunc, 5000);
}, 10);
};
sliderFunc();
scope.$watch('currentIndex', function() {
scope.images.forEach(function(image) {
image.visible = false; // make every image invisible
});
if (scope.images.length > 0) {
scope.images[scope.currentIndex].visible = true; // make the current image visible
}
});
scope.$on('$destroy', function() {
$timeout.cancel(timer); // when the scope is getting destroyed, cancel the timer
});
},
templateUrl: 'app/slider.tpl.html'
};
})
.directive('readMore', function() {
return {
restrict: 'A',
scope: true,
link: function(scope, elem, attrs) {
scope.more = false;
elem.find('.readmore').bind('click', function() {
scope.more = scope.more === false ? true : false;
});
}
};
});
两个指令都按预期工作。
第一个指令使用 $timeout,因此幻灯片图像每 5 秒循环一次。
阅读更多 link 中存在问题。 当我单击 link 时,脚本(指令)等待(最多)5 秒。执行,同时幻灯片也执行。
我是 Angular 的新手,但我认为具有不同范围的指令不会相互干扰。
我该怎么做才能让阅读更多 links 立即触发?
发生这种情况是因为在第二个指令中,您正在 jQuery 单击事件中更新范围,该事件超出了 Angular 生命周期。
视图将在下一个摘要周期刷新,例如由任何 $timeout
调用触发。
一个快速而肮脏的解决方法是在你的点击侦听器中调用第二个指令的 scope.$apply()
(或 scope.$digest()
)。
更好的解决方法是使用 ng-click
指令而不是 jQuery 侦听器以 angular 方式捕获点击事件(然后让它们成为其生命周期的一部分 -无需手动 $apply)
更新: 这里是如何使用ng-click
:
<a class="readmore" ng-click="more = !more">Read more</a>
作为旁注,您可能应该使用
$interval
而不是 $timeout
因为它是您实际模拟的内容。
您在 angular 上下文之外修改 scope.more。请在那里调用 scope.$digest()
elem.find('.readmore').bind('click', function() {
scope.more = scope.more === false ? true : false;
scope.$digest();
});