【问题标题】:AngularJS: callback after render (work with DOM after render)AngularJS:渲染后的回调(渲染后使用 DOM)
【发布时间】:2016-03-10 06:21:22
【问题描述】:

如何在渲染模板后运行方法$scope.myWork()?我想设置$scope.value,然后我需要用 JQuery 改变一些东西(例如在模板内容的 DOM 中)。 $scope.$watch('value', function (){....}) 正在“在”渲染之前工作(模板的 DOM 尚不可用)。谢谢。

【问题讨论】:

    标签: angularjs


    【解决方案1】:

    创建一个directive,在链接函数中运行您的代码。 建立模板后调用链接函数。

    请参阅ng-click 了解一下。

    【讨论】:

    • 有我的例子,它不起作用 - jsfiddle.net/C6SUv/7 (为什么每次渲染后不调用 $scope.afterRender ?)。
    • 因为链接函数在它元素被渲染之后被调用一次,而不是在每次渲染角度之后被调用。为什么你不能创建指令做你需要用 jQuery 和更新角度的改变?在控制器内部操作 DOM 不是一个好习惯
    • 嗯。我必须以固定高度滚动 div。我有用于在字段列表中移动光标的按钮。我在 ngClick 中设置了 $scope.value,之后我需要在正确的位置滚动(通过 scrollTop)。这就是为什么我想在控制器内部使用 DOM 进行操作的原因。有什么想法吗?
    • 看看$anchorScroll 是否可以完成这项工作或为此创建服务(以使您的控制器更具可测试性)。制作一个指令,将 div 的实际“顶部”设置为控制器中的变量和滚动的服务将是一个很好的匹配。
    • 也许你想在 DIV 中创建一个带有控制器的指令,并且在每一行中你可以添加一个指令,在链接函数中(渲染后)它使用 DIV 中的控制器传递它'top ' 并且控制器滚动到它。在 childs(rows) 中,您将使用 require: '^DIVdirectiveName' 来获取控制器。看到这个更新小提琴jsfiddle.net/C6SUv/8
    【解决方案2】:

    我在属性指令中使用terminal 和transclude 在模型更新并呈现视图后调用作用域方法(在我的例子中是在$Resource.query 之后调整iframe 的大小):

    .directive('postRender', [ '$timeout', function($timeout) {
    var def = {
        restrict : 'A', 
        terminal : true,
        transclude : true,
        link : function(scope, element, attrs) {
            $timeout(scope.resize, 0);  //Calling a scoped method
        }
    };
    return def;
    }])
    

    $timeout 是黑魔法。 应该可以将JS方法声明为属性值并$parse它。

    所以我在ng-repeat 中使用它(在我的例子中,树是递归渲染的):

    <div post-render ng-repeat="r in regions | orderBy:'name'" ng-include="'tree_region_renderer.html'">
    

    【讨论】:

      【解决方案3】:

      我也遇到了这个问题,其他解决方案对我来说效果不佳,看起来 Protractor 必须解决的那种事情。对Protractor's client-side scripts 的快速回顾表明它使用angular.getTestability(element) 来了解何时实际运行测试。该方法一直等待,直到没有挂起的超时或 http 请求,然后运行您的回调。这是我的指令:

      export function afterRender ($timeout) {
      "ngInject";
        return {
            restrict: 'A',
            terminal: true,
            link: function (scope, element, attrs) {
              angular.getTestability(element).whenStable(function() {
                console.log('[rendered]');
              });
            }
        };
      }
      

      【讨论】:

      • 由于您在 Angular 应用程序中运行,您可以简单地注入 $browser 并使用其 notifyWhenNoOutstandingRequests() 方法注册一个回调。但请注意,这依赖于一些未记录的私有 API,可能会在没有通知的情况下中断。
      • 就我而言,我是从脚本驱动浏览器的。将来我将删除该指令并从驱动程序中调用 whenStable()
      【解决方案4】:

      Jens 上面的回答会起作用,但请注意,在较新的 AngularJS 版本(例如 1.2.3)上,您不能将 postRender 指令与 ng-repeat 结合为同一标签上的属性,因为它们都具有 transclude: true。在这种情况下,您必须删除 transclude 或使用带有 postRender 指令属性的单独标记。
      使用终端时还要注意属性的优先级:true,因为您最终可能会因为同一标签上的优先级更高而导致属性无效。

      【讨论】:

        【解决方案5】:

        我在寻找一种分析 DOM 渲染的方法时发现了这个页面。我找到了一个非常简单的解决方案,适用于我的用例。

        将 ng-init 处理程序附加到 DOM 元素并在处理程序函数中,使用 $timeout 来产生执行。示例:

        HTML:

        <div ng-init="foo()">
        

        JS:

        $scope.foo = function() {
            $timeout(function() {
                // This code runs after the DOM renders
            });
        });
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-10-30
          • 1970-01-01
          • 2014-09-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-12-23
          • 2020-11-23
          相关资源
          最近更新 更多