【问题标题】:AngularJS - Directive events and DOM renderingAngularJS - 指令事件和 DOM 渲染
【发布时间】:2013-06-14 10:15:39
【问题描述】:

在下面的代码中,我正在尝试使用模板(使用{{ 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 操作

标签: javascript html angularjs angularjs-directive angularjs-scope


【解决方案1】:

我看到你有一个关于为什么 id 在链接时不可用的答案,但我可以质疑使用 id 选择器的原因吗?有了指令后,您可以通过链接函数中 jqLit​​e/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 选择器引用元素。通过传递给链接函数的元素上下文使用 jqLit​​e/jquery 方法。

【讨论】:

    【解决方案2】:

    选项 1 - 更好

    不使用template 方法,而是将HTML 移到link 方法中。这使我们能够在编译之前手动 $interpolate 括号中的术语,然后使用 ID 选择器。请注意,如果不使用= 而不是@ 隔离范围绑定,这是不可能的,因为@ 绑定被推迟到以后,并且在link 方法中未定义(请参阅here 的更多信息)。

    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');
        }   
      }
    }); 
    

    Here is a fiddle


    选项 2

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

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

    这也需要将$timeout 注入指令中。

    【讨论】:

    • 非常感谢。我认为这是一个时间问题,但不知道如何解决。
    猜你喜欢
    • 2017-10-30
    • 2023-03-24
    • 2013-09-29
    • 2012-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多