AngularJS $ timeout不等待UI-Router在计算值之前完成渲染

时间:2015-11-09 22:13:42

标签: javascript angularjs angular-ui-router angular-amd

我正在使用angularJSrequirejs通过angularAMD将复杂的应用程序连接在一起。

我的一个州有两个简单的观点,如:

  $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有一条指令:

  .directive('checkViewOneBoxWidth', function ($timeout) {
    return {
      restrict: 'A',
      link: function (scope, elem, attrs) {
        var linkFunctionAfterDomComplete = function () {
          console.log(elem[0].scrollWidth);
        }
        $timeout(linkFunctionAfterDomComplete, 0);
      }
    }
  })

view2有一个样式表,可以为页面应用一些样式,包括更改height容器的widthview1

我希望函数linkFunctionAfterDomComplete在 之后计算元素的heightwidth属性 view2中的样式表,因此我将linkFunctionAfterDomComplete函数包含在$timeout()中。

来自console.log的{​​{1}}报告了此元素的大小,在checkViewOneBoxWidth中样式表的样式修改了此元素的大小之前,尽管事实上我们会期望view2使$timeout函数在应用linkFunctionAfterDomComplete样式并且DOM完成后计算此元素的大小。

如何让view2计算元素属性,这些元素属性反映了在完全呈现元素并应用了所有样式后反映元素真实状态的元素属性?

http://plnkr.co/edit/WjGogh?p=preview

1 个答案:

答案 0 :(得分:4)

您需要将函数传递给$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

不确定您的实际应用程序中是否存在相同的问题,但我认为无论如何都应该发布此问题。

基于编辑的新答案

问题是您的link元素位于视图模板中而不是index.html中。

如果您将其移至index.html,它将按预期工作(在这种情况下您不需要$timeout,除非您的真实应用程序从指令添加自定义HTML):

演示: http://plnkr.co/edit/m3sriF2YYH5T8y42R5Lr?p=preview

如果您将链接保留在视图模板中并保持超时,则基本上会发生这种情况:

  1. Angular将运行其编译函数来准备所有绑定和视图。
  2. 视图中的HTML将被插入到DOM中,指令将被执行,console.log将被添加到超时队列中。
  3. 现在已将link元素插入到DOM中,浏览器将开始检索CSS。超时队列中的console.log将执行。
  4. 请注意,CSS的提取是异步的,超时队列中的console.log将在CSS的提取和解析完成之前执行。

    另请注意,您可能会在不同的浏览器中看到不同的行为。

    有解决方案,但它可能会变得非常混乱。

    要了解更多信息:

    When is a stylesheet really loaded?

    我建议您只需将链接移至index.html。