在替换 ng-repeat 之前调用自定义指令链接函数

Posted

技术标签:

【中文标题】在替换 ng-repeat 之前调用自定义指令链接函数【英文标题】:custom directive's link function is invoked before ng-repeat is replcaed 【发布时间】:2016-11-14 05:29:51 【问题描述】:

我有以下指令:

.directive("picSwitcher", ["$timeout", function($timeout)
return 
    restrict: "A",
    scope: 
        pics: "=",
        fadeTime: "@",
        timeForPic:"@"
    ,
    template: '<img ng-repeat="pic in pics" src="pic.url" style="display: none"/>',
    link:   function ($scope, element)
                //some code...
                $(element.find("img")[0]).css(display: "block");
            
;
])

我的问题是,当我的链接函数被调用时 - ng repeat 还没有“编译”(这里应该使用什么词而不是编译?)

所以我试图设置未定义的 css.. ng-repeat 完成后如何强制链接功能运行?!

现在我正在通过将$(element.find("img")[0]).css(display: "block"); 替换为$timeout(function() $(element.find("img")[0]).css(display: "block");, 200); 来解决这个问题

但这感觉'hacky'

为了以更简单的方式实现我的目标,我还缺少什么吗? 一般来说,在自定义指令的链接函数中操作 ng-repeat dom 元素的最佳方法是什么?

谢谢, 吉米。

【问题讨论】:

也许你会在 html 中做模板而不是在directice 中它会起作用? 【参考方案1】:

您可以使用 JQLite 的 .ready() 函数。

    post: function postLink(scope, element) 
      element.ready(function() 
        //$(element.find("li")[0]).css(color: "red");
        element.find("li:first-child").css(color: "red");
      );
    

我还更改了您在指令中选择元素的方式。既然你有 element 可用,你可以只使用 JQLite。但是,要更改一个 CSS 类,您应该在 CSS 文件中进行。

在下面的 sn-p 中,我将 &lt;img&gt; 替换为 &lt;ul&gt;&lt;li&gt;,但它对图像的作用相同。

function myDirective() 
  return 
    template : '<ul><li ng-repeat="pic in pics">pic.name</li></ul>',
    scope: 
      pics: '='
    ,
    link: function(scope, element) 
        element.ready(function() 
          //$(element.find("li")[0]).css(color: "red");
          element.find("li:first-child").css(color: "red");
        );
    
  

function SuperController() 
	this.pics = [name:"rob", name:"jules", name:"blair"];

angular.module('myApp', []);
angular
    .module('myApp')
    .controller('SuperController', SuperController)
    .directive('myDirective', myDirective);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<div ng-app="myApp">
  <div ng-controller="SuperController as s">
    <my-directive pics="s.pics">
    </my-directive>
  </div>
</div>

【讨论】:

好像是这样。不知道为什么!!谢谢你的回答:) 我认为这是一个比公认的答案更好的答案【参考方案2】:

您可以查看$scope.$evalAsync

$scope.$evalAsync(function()
    $(element.find("img")[0]).css(display: "block");

这将使函数在 dom 渲染后执行。

此外,如果您将延迟设置为 0,使用 $timeout 也不是一个坏主意

$timeout(function()
    $(element.find("img")[0]).css(display: "block");, 
0);

我想也可以。

更多参考http://www.bennadel.com/blog/2605-scope-evalasync-vs-timeout-in-angularjs.htm

【讨论】:

谢谢,根据您的参考,在我的情况下最好使用 $evalAsync 方法:) 但我很高兴看到我没有做错事。干杯。

以上是关于在替换 ng-repeat 之前调用自定义指令链接函数的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS:如何使用自定义指令来取代ng-repeat

AngularJs ng-repeat指令中怎么实现含有自定义指令的动态html

Angular 自定义指令在 ng-repeat 中使用 if 条件

AngularJS ng-repeat 与表格内的自定义元素呈现奇怪

AngularJs 使用自定义 Json 中的 ng-repeat 创建表

ng 使用自定义指令重复