我正在通过 PhantomJS 通过 Selenium 为搜索引擎机器人预渲染 HTML 页面,以便他们可以看到完全加载的内容。目前,在 PhantomJS 到达页面后,我等待 5 秒,以便确定所有内容都已加载。
我考虑的一个解决方案是等到属性 html-ready
出现,而不是每次都等待 5 秒。关于<body />
标签设置为 true:
<html ng-app>
<head>...</head>
<body html-ready="{{htmlReady}}">
...
</body>
</html>
.controller("AnyController", function($scope, $rootScope, AnyService) {
$rootScope.htmlReady = false;
AnyService.anyLongAction(function(anyData) {
$scope.anyData = anyData;
$rootScope.htmlReady = true;
});
})
问题是: html-ready
会吗?完成任何 View 更新后,属性始终设置为 true (例如显示 anyData
)?换句话说,有没有可能在一圈中,html-ready
属性是true
当页面尚未完全加载时?如果有,该如何处理?
最佳答案
它应该在摘要之后完成,这样它就有更多的机会按预期工作。
AnyService.anyLongAction(function(anyData) {
$scope.anyData = anyData;
$timeout(function () {
$rootScope.htmlReady = true;
}, 0, false);
});
但就应用程序而言,它毫无用处。您必须注意每个地方的变化,Angular 没有提供任何东西来使任务变得更容易。
幸运的是,您可以自由地从 Angular 中进行抽象并保持简单。
var ignoredElements = [];
ignoredElements = ignoredElements.concat($('.continuously-updating-widget').toArray());
var delay = 200; // add to taste
var timeout;
var ready = function () {
$('body').off('DOMSubtreeModified');
clearTimeout(timeoutLimit);
alert('ready');
};
$('body').on('DOMSubtreeModified', function (e) {
if (ignoredElements.indexOf(e.target) < 0) {
clearTimeout(timeout);
timeout = setTimeout(ready, delay);
}
});
var timeoutLimit = setTimeout(ready, 5000);
如果需要,请随意对其进行 Angular 化,尽管它无论如何都不是生产代码。
最好将处理程序放入节流包装函数中(该事件将一直发送垃圾邮件)。如果您在页面上使用可能超过超时延迟的远程请求,则最好将此方法与异步服务的多个 Promise 结合起来,并使用 $q.all
解决它们。尽管如此,这还是比照顾每一个指令和服务要好得多。
DOMSubtreeModified
被认为已过时(它从未被真正承认,建议使用 MutationObserver
),但当前版本的 FF 和 Chrome 支持它,并且应该对于 Selenium 来说还可以。
关于javascript - 如何使用 AngularJS 影响 HTML 渲染优先级?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29711556/