【问题标题】:Checking for defined functions in nested directives检查嵌套指令中定义的函数
【发布时间】:2015-12-28 11:42:45
【问题描述】:

当将函数传递到指令中,然后传递到嵌套的子指令中时,在子指令的范围内检查时始终认为该函数已定义,无论它是否在父指令中传递。

在处理嵌套指令时是否有更好的方法来传递函数指针或检查它们是否已定义。

plunker

<body ng-app="myApp">
  <div ng-controller="myController">
    <dir1"></dir1>
  </div>

  <script type="text/ng-template" id="dir1">
    <div>
      <dir2 fun="fun()"></dir2>
    </div>
  </script>
  <script type="text/ng-template" id="dir2">
    <div>{{fun()}}</div>
    <div>{{funDefined()}}</div> <!-- always true-->
  </script>
</body>

var app = angular.module('myApp', []);

app.controller('myController', function($scope) {
  $scope.fun = function() {
    alert("function");
  };
});

app.directive('dir1', function() {
  return {
    scope: {
      fun: '&'
    },
    templateUrl: 'dir1'
  };
});

app.directive('dir2', function() {
  return {
    scope: {
      fun: '&'
    },
    link: function(scope, elem, attrs) {
      scope.funDefined = function() {
        return angular.isDefined(attrs.fun);
      };
    },
    templateUrl: 'dir2'
  };
});

【问题讨论】:

  • 好吧,但就 dir2 而言,它定义的。调用者有责任提供正确的参数。

标签: javascript angularjs


【解决方案1】:

如果您在 dir2 的 scope.funDefined 方法中设置调试器,您将看到 attrs.fun 等于字符串 "fun()"。那是因为您从属性中获取原始价值。由于它不是空字符串,它总是会给你true

这里更新plunker

【讨论】:

    【解决方案2】:

    我知道没有优雅的方式可以得到你想要的东西。就像在这行之前提到的那样:

    angular.isDefined(attrs.fun)
    

    对字符串执行检查,因此每次定义fun 属性时都会返回true。在你的 dir1 指令模板中你有 &lt;dir2 fun="fun()"&gt;&lt;/dir2&gt; 所以 fun 显然是定义的(它是字符串)。如果您查看 Angular 的来源:

    case '&':
                // Don't assign Object.prototype method to scope
                parentGet = attrs.hasOwnProperty(attrName) ? $parse(attrs[attrName]) : noop;
    
                // Don't assign noop to destination if expression is not valid
                if (parentGet === noop && optional) break;
    
                destination[scopeName] = function(locals) {
                  return parentGet(scope, locals);
                };
                break;
    

    您会看到该属性的存在将始终导致某些函数分配给范围($parse 即使对于没有多大意义的字符串也会返回函数)。

    所以我能想到的唯一解决方案是在第一级指令中执行检查(有可能因为属性确实未定义)并有两个 &lt;dir2&gt; 标签(有和没有fun 属性) - 一个总是被排除在外使用ng-if。像this 这样的东西。再说一次,我知道,它的解决方案很丑。

    附带说明 - Angular 的源代码还显示,如果没有属性并且绑定是可选的(使用 &amp;?),则不会设置范围属性 - 然后您可以检查 scope.fun 值而不是 attrs.fun - 有些人可能会发现它更优雅。

    【讨论】:

      【解决方案3】:

      我能找到的最好方法是基于@xersiee 在另一个答案中的评论。这个想法是在父指令中使作用域参数可选,然后使用angular.isUndefined(scope.$parent.$eval(attribute.myFun)) 检查函数是否被传递。这在官方文档中没有解释......我想知道为什么。

      正如其他人所提到的,这种解决方案远非理想,因为使用 scope.$parent 是一种反模式,但同样,这是我能找到的最佳选择。

      使用此解决方案的 Plunker:http://plnkr.co/edit/SUUMae?p=preview

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-23
        • 2015-10-22
        • 1970-01-01
        • 1970-01-01
        • 2013-06-15
        • 1970-01-01
        相关资源
        最近更新 更多