【问题标题】:Angularjs isolated scope for directives without own templateAngularjs隔离了没有自己模板的指令范围
【发布时间】:2014-01-02 08:13:33
【问题描述】:

我想在没有自己的模板的情况下在 AngularJS 中创建可重用指令。我还希望该指令具有独立的范围。我的方法的最佳实践是什么? 为什么我的示例没有按预期工作?

我希望我可以分别从指令中编辑 obj1 和 obj2。

HTML:

<div ng-controller="MyCtrl">
  X1: {{ obj1.x }}, Y1: {{ obj1.y }}
  X2: {{ obj2.x }}, Y2: {{ obj2.y }}
  <hr>
  Edit obj1: 
  <div draggable target="obj1">
    <input type="text" ng-model="target.x">
    <input type="text" ng-model="target.y">
  </div>
  Edit obj2:
  <div draggable target="obj2">
    <input type="text" ng-model="target.x">
    <input type="text" ng-model="target.y">
  </div>
</div>

JS:

angular.module("App", [])
  .controller("MyCtrl", function($scope) {
    $scope.obj1 = {
      x: 10,
      y: 20
    };
    $scope.obj2 = {
      x: 30,
      y: 40
    };
  })
  .directive("draggable", function() {
    return {
      scope: {
        target: "="
      },
      link: function(scope, el, attrs) {
        console.log("scope: ", scope);
      }
    }
  });

PLUNKR: http://plnkr.co/edit/Dw8IiFVSOZGjSTFGRMzZ

【问题讨论】:

  • 为什么不能使用模板?
  • @Cherniv,这只是一个例子。实际应用程序的用法是这样的:&lt;div class="block" ng-repeat="block in layout.blocks" size resizable resizable-width="block.width" resizable-height="block.height" draggable draggable-top="block.top" draggable-left="block.left" in-bounds bounds-width="stripe.width" bounds-height="stripe.height"&gt;...&lt;/div&gt; 如果我为每个指令使用模板,代码会看起来(更)丑陋和不可读。

标签: javascript angularjs angularjs-directive angularjs-scope


【解决方案1】:

您的代码现在的工作方式是,每个指令的内容都绑定到父范围,而不是指令的隔离范围,因此每个 target 都是对同一变量的引用。

您需要做的是transclude 指令的内容。这样做的通常用途是您希望内容在指令的父范围内,而不是在隔离范围内。但是,您希望内容位于指令的隔离范围内。所以你必须手动调用transclude 函数,并将内容绑定到指令的隔离范围:

.directive("draggable", function($compile) {
  return {
    transclude: true,
    scope: {
      target: "="
    },
    link: function(scope, element, attrs, ctrl, transclude) {
      transclude(scope, function(clone) {
       element.append(clone);
      });
    }
  }
})

您可以see this in this Plunker。它没有做的一件事是$watch 'target' 的内容,所以我怀疑它不会对指令上的“target”属性的变化做出反应。这可能最好留给另一个问题。

编辑:transclude 的使用不正确/过于复杂。您可以将scope 作为第一个参数传入,以将克隆正确绑定到正确的范围。

【讨论】:

  • 明白了!我试图玩转隐藏,但没有效果。感谢您提供有用的模式!
  • 谢谢。我很好奇为什么 Angular 会这样。 transclude: true,link 带有 tranclude,并使用 scope 调用 transclude 函数。它必须比原来的方式更简单。
  • 喜欢这个答案,谢谢。我有一个案例,我认为将标记移动到指令的模板中但仍然能够操作这部分 DOM 是不合逻辑的。
  • “它没有做的一件事是 $watch 'target' 的内容” -- AFAICT 这很好用,至少在编辑后的版本中是这样。跨度>
【解决方案2】:

来到这里面临同样的困惑。显然,情况如下。

除了嵌入之外,只有指令模板中的元素才会绑定到该指令创建的隔离范围。如果您不使用模板 - 声明指令的元素的内容将绑定,就好像独立范围不存在一样。

这是一个从上面修改过的 plunker,展示了这一点。 http://plnkr.co/edit/WqEKkNAj4p2Rly51LBzC?p=preview

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-21
    • 1970-01-01
    • 1970-01-01
    • 2015-12-08
    相关资源
    最近更新 更多