AngularJS - 指令事件和DOM渲染

3
在下面的代码中,我试图使用模板(具有{{ value }}替换),但我已经尝试了两天,找到一种获取呈现代码并设置其某些属性的方法。
我无法使用样式选择器(它可以正常工作),我需要使用div的id。在我的实际代码中,我使用了一个templateUrl:,而不是内联代码,但结果相同。
我应该监听哪个事件?在什么时间点上选择器会起作用?我已经阅读了有关编译和链接的内容,并认为答案就在那里?
提前感谢...
<!doctype html>
<html lang="en" ng-app="myApp">
   <head>
      <meta charset="utf-8">
      <title>My AngularJS App</title>
      <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
   </head>
   <body style="height:100%; width: 100%;">
      <tls-window window-id="fred" window-width="600" window-label-width="150"></tls-window>
      <script src="lib/angular/angular.js"></script>
      <script src="js/app.js"></script>
      <script src="js/core/services.js"></script>
      <script src="js/core/controllers.js"></script>
      <script src="js/core/filters.js"></script>
      <script src="js/core/directives.js"></script>
      <script src="js/core/tlscore-directives.js"></script>
      <script type="text/javascript">

      var coreDirectives = angular.module('tlsCore.directives', []);
      coreDirectives.directive('tlsWindow', function() {
        return {
          restrict: 'E',
          scope: {
            windowId: '@windowId',
            windowWidth: '@windowWidth',
            labelWidth: '@windowLabelWidth'
          },
          replace: true,
          transclude: false,
          template: '<div id="{{windowId}}" class="tls-window" ng-cloak tls-draggable >' +
            '<div id="{{windowId}}-winBackground" class="tls-window-background" style="width: 300px; height: 200px" >' +
            '<div id="{{windowId}}-winToolbarBackground" class="tls-window-toolbar-background">' +
            '<div id="{{windowId}}-winToolbarContent" class="tls-window-toolbar-content" style="width: 300px; height: 100px">' +
            '</div>' +
            '</div>' +
            '</div>',
          link: function(scope, element, attrs) {
            var ele = element.get(element.index(scope.windowId));
            // this works and sets the colour (by class)
            $('.tls-window-toolbar-content').css("background-color", 'red');
            // this does not work as the id of the element is not yet substituted and rendered ??
            $('#fred-winBackground').css("background-color", 'green');
          }
        }
      });   

      </script>
   </body>
</html>

如果你想进行子DOM操作,我建议你使用prelink和postlink函数替换链接,并在postlink函数中进行DOM操作。 - Ajay Beniwal
2个回答

1

选项1 - 更好

不要使用template方法,而是将HTML代码移到link方法中。这样我们就可以在编译之前手动$interpolate括号内的术语,然后使用ID选择器。请注意,如果不使用=而使用@隔离作用域绑定,则无法实现此操作,因为@绑定会被推迟到稍后,并且在link方法中未定义(有关详细信息,请参见此处)。

app.directive('tlsWindow', function($interpolate,$compile) {
  return {
    restrict: 'E',
    scope: {
        windowId: '=',
        windowWidth: '=',
        labelWidth: '='
    },
    link: function (scope, element, attrs) {
        var template = '<div id="{{windowId}}" class="tls-window" ng-cloak tls-draggable >' +
        '<div id="{{windowId}}-winBackground" class="tls-window-background" style="width: 300px; height: 200px" >' +
            '<div id="{{windowId}}-winToolbarBackground" class="tls-window-toolbar-background">' +
                '<div id="{{windowId}}-winToolbarContent" class="tls-window-toolbar-content" style="width: 300px; height: 100px">' +
                '</div>' +
            '</div>' +
        '</div>';

        var interpolated = $interpolate(template)(scope);
        var html = $(interpolated);
        element.replaceWith($compile(html)(scope));
        
        $('.tls-window-toolbar-content').css('background-color', 'red');
        $('#fred-winBackground').css('background-color', 'green');
    }   
  }
}); 

这里有一个小提琴


选项2

虽然不是最强大的解决方案,但这也可以工作。在这里,使用$timeout将操作推迟到渲染之后。这也会导致轻微的延迟。

$timeout(function(){
    $('#fred-winBackground').css("background-color", 'green');
},0);

这需要在指令中注入$timeout

非常感谢。我以为这是一个时间问题,但是不知道如何解决它。 - user2496423

0

我看到你已经回答了关于为什么在链接时id不可用的问题,但我是否可以质疑使用id选择器的原因?一旦你有了指令,你可以通过链接函数中jqLite / jquery元素的children方法访问模板中顶级div。请参考以下示例:

angular.module('myApp', [])
.directive('tlsWindow', function() {
        return {
          restrict: 'E',
          scope: {
            windowId: '@windowId',
            windowWidth: '@windowWidth',
            labelWidth: '@windowLabelWidth'
          },
          replace: true,
          transclude: false,
          template: '<div id="{{windowId}}" class="tls-window" ng-cloak tls-draggable >' +
            '<div id="{{windowId}}-winBackground" class="tls-window-background" style="width: 300px; height: 200px" >' +
            '<div id="{{windowId}}-winToolbarBackground" class="tls-window-toolbar-background">' +
            '<div id="{{windowId}}-winToolbarContent" class="tls-window-toolbar-content" style="width: 300px; height: 100px">' +
            '</div>' +
            '</div>' +
            '</div>',
          link: function(scope, element, attrs) {
            // var ele = element.get(element.index(scope.windowId));
            // this works and sets the colour (by class)
            // $('.tls-window-toolbar-content').css("background-color", 'red');
            // this does not work as the id of the element is not yet substituted and rendered ??
            // $('#fred-winBackground').css("background-color", 'green');
            
            // Use the jqlite or jquery children method to locate the first child of your directive
            // element (from linkFn) is the element of tls-window and children() gets you access to the <div> container in your template
            element.children().css("background-color", "green");
          }
        }
      });
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="myApp">
  <tls-window window-id="fred" window-width="600" window-label-width="150"></tls-window>
</div>

AngularJS 不鼓励通过 ID 选择器引用元素。请利用传递给链接函数的元素上下文中的 jqLite/jQuery 方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接