AngularJS $timeout isn't waiting for UI-Router to finish rendering before computing values
Я использую angularJS
а также requirejs
с помощью angularAMD
to wire together a complex application.
One of my states has two simple views like so:
$stateProvider
.state("common", {
url: "/",
views: {
"view1": {
templateUrl: "view1.tpl.html"
},
"view2": {
templateUrl: "view2.tpl.html"
}
}
});
HTML
<div ui-view="view1"></div>
<div ui-view="view2"></div>
View1
has a directive:
.directive('checkViewOneBoxWidth', function ($timeout) {
return {
restrict: 'A',
link: function (scope, elem, attrs) {
var linkFunctionAfterDomComplete = function () {
console.log(elem[0].scrollWidth);
}
$timeout(linkFunctionAfterDomComplete, 0);
}
}
})
А также view2
has a stylesheet that applies some styling to the page, including changing the height
а также width
из view1
контейнер.
Я хочу функцию linkFunctionAfterDomComplete
to compute the element's height
а также width
properties after the DOM has been modified by the stylesheet in view2
, so I wrapped the linkFunctionAfterDomComplete
функция в $timeout()
,
console.log
от checkViewOneBoxWidth
here is reporting the size of this element, before the styling from the stylesheet in view2
modified the size of this element, despite the fact that we would expect the $timeout
to cause the linkFunctionAfterDomComplete
function to calculate the size of this element after styling from view2
is applied and the DOM is complete.
Как я могу получить linkFunctionAfterDomComplete
to calculate element properties that reflect those which reflect the true state of the element after it had been fully rendered and all styling has been applied?
1 ответ
Вам нужно передать функцию $timeout
:
$timeout(function() {
console.log('timeout: view 1 linked')
}, 0);
Или же:
var fn = function () {
console.log('timeout: view 1 linked');
};
$timeout(fn, 0);
Следующие:
$timeout(console.log('timeout: view 1 linked'), 0);
Выполнит console.log
мгновенно затем передать возвращаемое значение (undefined
) в качестве первого аргумента $timeout
,
Демонстрация: http://plnkr.co/edit/zWgoJihcMH693fWfUp09?p=preview
Не уверен, что у вас есть такая же проблема в вашем реальном приложении, но я решил, что я все равно должен это опубликовать.
Новый ответ на основе редактирования
Проблема в том, что ваш элемент ссылки находится в шаблоне представления, а не в index.html.
Если вы переместите его в index.html, он будет работать так, как вы ожидаете (и вам не нужно $timeout
в этом случае, если ваше реальное приложение не добавляет пользовательский HTML из директивы):
Демоверсия: http://plnkr.co/edit/m3sriF2YYH5T8y42R5Lr?p=preview
Если вы сохраняете ссылку в шаблоне представления и сохраняете время ожидания, это в основном то, что происходит:
- Angular запустит функцию компиляции, чтобы подготовить все привязки и представления.
- HTML из представлений будет вставлен в DOM, директивы будут выполнены и
console.log
будут добавлены в очередь времени ожидания. - Элемент ссылки теперь вставлен в DOM, и браузер начнет извлекать CSS.
console.log
в очереди ожидания будет выполняться.
Обратите внимание, что выборка CSS является асинхронной и console.log
по истечении времени ожидания очередь будет выполняться до завершения извлечения и анализа CSS.
Также обратите внимание, что вы можете увидеть различное поведение в разных браузерах.
Есть решения, но они могут стать очень грязными.
Чтобы узнать больше об этом:
Когда действительно загружается таблица стилей?
Я бы порекомендовал просто переместить ссылку на index.html.